Je souhaite renommer des milliers de fichiers.
Chaque nom de fichier a l'une des structures suivantes:
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:
Comment pourrais-je faire cela en utilisant une commande Bash?
3 Réponses :
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 }
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
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
.
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.