Un petit truc vraiment sympa. find + perl + xargs + mv
xargs -n2
permet d'imprimer deux arguments par ligne. Combiné à la fonction print $_
(pour imprimer le $STDIN en premier), il constitue un puissant outil de renommage.
find . -type f | perl -pe 'print $_; s/input/output/' | xargs -d "\n" -n2 mv
Résultats de perl -pe 'print $_; s/OldName/NewName/' | xargs -n2
finissent par l'être :
OldName.ext NewName.ext
OldName.ext NewName.ext
OldName.ext NewName.ext
OldName.ext NewName.ext
Je ne disposais pas de la fonction rename
disponible sur mon système.
Comment cela fonctionne-t-il ?
-
find . -type f
produit des chemins d'accès aux fichiers (ou des noms de fichiers... vous contrôlez ce qui est traité par les expressions rationnelles ici !)
-
-p
imprime les chemins d'accès aux fichiers qui ont été traités par les expressions rationnelles, -e
exécute un script en ligne
-
print $_
imprime d'abord le nom du fichier original (indépendamment de -p
)
-
-d "\n"
coupe l'entrée par une nouvelle ligne, au lieu du caractère espace par défaut
-
-n2
imprime deux éléments par ligne
-
mv
récupère l'entrée de la ligne précédente
Mon approche préférée, bien que plus avancée.
Supposons que je veuille renommer tous les fichiers ".txt" en fichiers ".md" :
find . -type f -printf '%P\0' | perl -0 -l0 -pe 'print $_; s/(.*)\.txt/$1\.md/' | xargs -0 -n 2 mv
La magie réside dans le fait que chaque processus du pipeline prend en charge l'octet nul (0x00) qui est utilisé comme délimiteur par opposition aux espaces ou aux nouvelles lignes. La méthode susmentionnée utilise les nouvelles lignes comme séparateurs. Non pas que j'aie essayé de supporter facilement find .
sans utiliser de sous-processus. Soyez prudent ici (vous pourriez vouloir vérifier votre sortie de find
avant de le soumettre à une expression régulière ou, pire encore, à une commande destructrice telle que mv
).
Fonctionnement (abrégé pour n'inclure que les changements ci-dessus)
- En
find
: -printf '%P\0'
n'imprime que le nom des fichiers sans chemin d'accès suivi d'un octet nul. Adaptez-vous à votre cas d'utilisation, qu'il s'agisse de noms de fichiers ou de chemins entiers.
- En
perl
y xargs
: -0
le délimiteur stdin est l'octet nul (au lieu de l'espace)
- En
perl
: -l0
le délimiteur de stdout est l'octet nul (en octal 000)