1
votes

Renommer plusieurs fichiers séparés par un caractère spécial en modifiant l'ordre

Je souhaite renommer des milliers de fichiers.

Chaque nom de fichier a l'une des structures suivantes:

  • aa - bb.txt
  • aa - bb - cc.txt
  • aa - bb - cc - dd.txt
  • aa - bb - cc - dd - ee.txt

Avec [aa], [bb], [cc], [dd] et [ee] changeant entre les fichiers et variant en longueur.

Je voudrais avoir le dernier élément avant .txt (le nom du fichier se compose de plusieurs caractères spéciaux - ) au début.

Pour les exemples ci-dessus, cela entraînerait:

  • bb - aa.txt
  • cc - aa - bb.txt
  • dd - aa - bb - cc.txt
  • ee - aa - bb - cc - dd.txt

Comment pourrais-je faire cela en utilisant une commande Bash?


2 commentaires

Sont-ils tous dans un seul répertoire ou répartis sur tout le système de fichiers?


@MarkSetchell, tous les fichiers sont dans un seul répertoire.


3 Réponses :


1
votes

Vous pouvez utiliser cette fonction zsh:

rename *
rename () {
    setopt local_options re_match_pcre
    if [[ "$1" =~ '(.*) - ([^-]*)(\.[^.]*)$' ]]
    then
        mv -i "$1" "${match[2]} - ${match[1]}${match[3]}"
    fi
}


0 commentaires

4
votes

Comme toujours, sauvegardez vos fichiers ou testez sur un sous-ensemble copié avant d'exécuter des commandes inconnues aussi puissantes que celle-ci ...

Je pense que vous pouvez le faire avec rename , alias Perl rename comme ceci:

brew install rename

Exemple de sortie

find . -name "*-*.txt" -print0 " | rename -0 -n 's/.txt$//; my @F=split / - /; $_ = join " - ", pop @F, @F; $_ .= ".txt"'

Si vous n'êtes pas familier avec Perl, cela signifie ... "Renommer en tant que run-run sans rien faire à cause de -n . Supprimez l'extension .txt . Divisez le nom de fichier sur" espace-espace "en une liste appelée F Créez un nouveau afficher le nom de fichier en joignant le dernier élément sorti de la liste F à tous les éléments restants de la liste F utilisant " - " pour séparer les éléments. Remettez l'extension ".txt". "


Si vous avez tellement de fichiers que vous obtenez l'erreur «Liste d'arguments trop longue» , vous pouvez la refactoriser en:

'aa - bb - cc - dd - ee.txt' would be renamed to 'ee - aa - bb - cc - dd.txt'
'aa - bb - cc - dd.txt' would be renamed to 'dd - aa - bb - cc.txt'
'aa - bb - cc.txt' would be renamed to 'cc - aa - bb.txt'
'aa - bb.txt' would be renamed to 'bb - aa.txt'

Ajoutez -maxdepth 1 dans la commande find si vous ne voulez pas rentrer dans les répertoires inférieurs.


Si quelqu'un essaie cela sur macOS, vous pouvez installer la commande de rename correcte avec homebrew en utilisant:

rename -n 's/.txt$//; my @F=split / - /; $_ = join " - ", pop @F, @F; $_ .= ".txt"' *.txt


0 commentaires

2
votes

Avec une solution pure BASH, pourriez-vous s'il vous plaît essayer de suivre. Testé et écrit uniquement avec les échantillons illustrés.

mv "aa - bb - cc - dd - ee.txt" "ee - aa - bb - cc - dd.txt"
mv "aa - bb - cc - dd.txt" "dd - aa - bb - cc.txt"
mv "aa - bb - cc.txt" "cc - aa - bb.txt"
mv "aa - bb.txt" "bb - aa.txt"

La sortie sera la suivante.

for fileName in *.txt
do
  lastPartFileName="${fileName##*- }"
  firstPartFileName="${fileName%- *}"
  firstPartFileName1="${fileName## *}"
  firstPartFileName2="${firstPartFileName1% *}"
  firstPartFileName3=${firstPartFileName2% -*}
  lastPartFileName1=$(echo "$lastPartFileName" | cut -d'.' -f1)
  echo "mv \"$fileName\" \"$lastPartFileName1 - $firstPartFileName3.txt\""
done

Il affichera les commandes mv (renommer) une fois que vous serez satisfait des résultats, puis exécutera le suivi en ajoutant | bash à la commande ci-dessus après avoir done comme done | bash .


0 commentaires