web-dev-qa-db-fra.com

Batch renommer des fichiers en ligne de commande et Xargs

Donc, j'ai la structure suivante:

.
..
a.png
b.png 
c.png

J'ai lancé une commande pour les redimensionner

ls | xargs -I xx convert xx -resize xx.jpg

Maintenant, mon dir ressemble à ceci

.
..
a.png.jpg
a.png
b.png.jpg
b.png
c.png.jpg
c.png

La première question est de savoir comment puis-je renommer le fichier afin que je puisse avoir juste une extension. Pas deux. (fondamentalement, comment puis-je nettoyer mon erreur d'origine)?

La seconde question est, à l'avenir, en utilisant xargs, comment puis-je changer l'extension du fichier simular en seconde commande?

22
Cripto

comment puis-je renommer le fichier afin que je puisse avoir juste une extension.

cd dir/with/messedup/files

for file in *.png.jpg; do
  mv "$file" "${file%.png.jpg}.jpg"
done

à l'avenir, en utilisant xargs, comment puis-je changer l'extension du fichier simular en seconde commande?

À ma connaissance, cela ne peut être fait. La meilleure façon de le faire serait d'utiliser une boucle for avec une substitution de paramètre très semblable à celle ci-dessus:

for file in *.png; do
  convert "$file" -resize "${file%.png}.jpg"
done

Si vous souhaitez convertir des fichiers dans des sous-répertoires, vous pouvez rediriger find vers une boucle while read:

find . -type f -name '*.png' |
while read file; do
  convert "$file" -resize "${file%.png}.jpg"
done

NOTE: Il est généralement considéré comme une mauvaise idée d'utiliser le résultat de ls dans un script Shell. Bien que votre exemple ait peut-être bien fonctionné, il existe beaucoup d'exemples dans lesquels ce n'est pas le cas. Par exemple, si vos noms de fichiers contiennent des retours à la ligne (ce que permet unix), ls ne leur échappera probablement pas. (Cela dépend en fait de votre implémentation, ce qui est une autre raison de ne pas utiliser ls dans les scripts; son comportement varie grandement d'une boîte à l'autre.) Vous obtiendrez des résultats plus cohérents si vous utilisez soit find dans une boucle while/read fichier globbing (par exemple *.png) dans une boucle for.

19
Tim Pote

Cela peut également être fait avec xargs et sed pour changer l'extension de fichier.

ls | grep \.png$ | sed 'p;s/\.png/\.jpg/' | xargs -n2 mv

Vous pouvez imprimer le nom de fichier d'origine avec ce que vous voulez que le nom de fichier soit. Puis, xargs utilise ces deux arguments dans la commande move. Pour one-liner, j'ai également ajouté un grep pour filtrer tout ce qui n'est pas un fichier * .png.

49
Schleis

Arriver en retard à la fête, mais voici comment vous pouvez renommer des fichiers avec xargs. Supposons que vous avez un groupe de fichiers nommé fileN.svg.png et que vous voulez les nommer fileN.png, où N pourrait être une série d’entiers:

ls *.svg.png | xargs basename -s .svg.png | xargs -I {} mv {}.svg.png {}.png

Le premier xargs utilise le nom de base pour supprimer les fichiers .svg et .png afin d'obtenir une variable filenameN. Le second xargs reçoit ce nom et utilise remplacement pour renommer le fichier.

10
Dethe

Pour effacer votre erreur, essayez l'utilitaire rename. Consultez la page de manuel pour plus de détails.

Dans votre cas, vous feriez rename '.png.jpg' '.jpg' ./* si votre répertoire actuel est correctement défini.

Puisque vous avez convert disponible, je suppose que vous avez aussi mogrify (imagemagick suite). Chaque fois que je veux faire cela, je copie les fichiers dans un répertoire différent et utilise plutôt mogrify. J'ai généralement besoin de cela uniquement pour le redimensionnement, mais si vous modifiez le format de l'image également, mogrify gérera les noms de fichiers (créez de nouveaux fichiers avec les noms de fichiers appropriés).

Vous l'utiliseriez comme mogrify -format jpg -resize [size] ./*.png. Je ne sais pas ce que -resize sans arguments de géométrie est censé faire. Ce n'est pas documenté et ne fonctionne pas sur ma machine.

Comme le pensait Tim Pote, je ne pense pas que vous puissiez faire en sorte que xargs gère les noms de fichiers et les extensions séparément.

6
Matej

Je suis en retard à cette fête d'environ 3 ans, je viens d'avoir un problème similaire que j'ai résolu moi-même. J'avais une liste de fichiers png que j'ai convertis à l'aide d'inkscape, car le support svg d'ImageMagick est médiocre. 

Je les ai initialement convertis en faisant:

find . -name "*.svg" -exec inkscape {} --export-png={}.png

Ce qui a bien sûr conduit au même problème que celui affiché ci-dessus.

file1.svg
file1.svg.png
file2.svg
file2.svg.png
file3.svg
file3.svg.png
file4.svg
file4.svg.png

Je voulais renommer * .svg.png en * .png, c’est ce avec quoi je me suis retrouvé ...

find . -name "*.svg.png" -print0 | sed 's/.svg.png//g' | xargs -0 -I namePrefix mv namePrefix.svg.png namePrefix.png

Cela fait trois choses:

  1. rechercher dans ce répertoire les fichiers nommés * .svg.png, l’impression -print0 sur la sortie standard
  2. sed modifie la sortie standard, swap .svg.png sans rien, donc j'obtiens: fichier1/fichier2/fichier3/fichier4
  3. xargs -0 pour obtenir les données de sed, -I fait référence au nom du fichier sans extension, puis mv nom de fichier d'origine au nouveau nom de fichier. Le mot namePrefix n'a rien de spécial, je voulais juste que ce soit clair.

MODIFIER

Je réalise maintenant que c’est la manière la plus compliquée de le faire. On peut simplement utiliser la commande renommer.

rename 's/svg\.png/.png/' *
3
Paul J

Ma solution est similaire à beaucoup de solutions xarg et particulièrement à celle de Schleis.

La différence ici est une manipulation de regex complète avec des références de correspondance et des commandes sed qui ignorent correctement les fichiers qui ne correspondent pas, de sorte que vous n'avez pas besoin de préfiltrer votre liste.

Ceci est également sûr pour les fichiers avec des espaces et méta Shell.

Remplacez \2 par le remplacement par n'importe quel poste de votre choix.

ls |
sed -nE 's/Rick\.and\.Morty\.(S03E[0-9]{2})\..*(\.[a-z0-9]{3})/"&" "Rick and Morty \1\2"/;T;p' |
xargs -n 2 mv

Explication

Le -n arg indique ne rien imprimer par défaut, la commande T indique de passer à la fin du script si la précédente commande s n'a pas remplacé, la commande p imprime l'espace du modèle (uniquement si la commande s correspond ).

Le & dans le remplacement est une référence au contenu de la correspondance de nom de fichier d'origine.

Si nous remplaçons mv dans la commande par bash -c 'echo "run($#) $@"' bash, nous pourrons voir le nombre d'appels de mv, ainsi que le nombre de paramètres et la valeur:

$ ls |
  sed -nE 's/Rick\.and\.Morty\.(S03E[0-9]{2})\..*(\.[a-z0-9]{3})/"&" "Rick and Morty \1\2"/;T;p' |
  xargs -n 2 bash -c 'echo "run($#) $@"' bash
run(2) Rick.and.Morty.S03E02.720p.HDTV.x264-BATV.mkv Rick and Morty S03E02.mkv
run(2) Rick.and.Morty.S03E03.720p.HDTV.x264-BATV.mkv Rick and Morty S03E03.mkv
run(2) Rick.and.Morty.S03E04.720p.HDTV.x264-BATV.mkv Rick and Morty S03E04.mkv
run(2) Rick.and.Morty.S03E05.HDTV.x264-BATV[ettv].mkv Rick and Morty S03E05.mkv
run(2) Rick.and.Morty.S03E06.720p.HDTV.x264-BATV.mkv Rick and Morty S03E06.mkv
run(2) Rick.and.Morty.S03E06.HDTV.x264-BATV.mkv Rick and Morty S03E06.mkv
run(2) Rick.and.Morty.S03E07.720p.HDTV.x264-BATV[ettv].mkv Rick and Morty S03E07.mkv
run(2) Rick.and.Morty.S03E08.720p.HDTV.x264-BATV.mkv Rick and Morty S03E08.mkv
run(2) Rick.and.Morty.S03E09.720p.HDTV.x264-BATV.mkv Rick and Morty S03E09.mkv
run(2) Rick.and.Morty.S03E10.720p.HDTV.x264-BATV.mkv Rick and Morty S03E10.mkv
1
joshperry

Ma tentative de: https://www.tecmint.com/linux-image-conversion-tools/

ls -1 *.png | xargs -n 1 bash -c 'convert "$0" "${0%.png}.jpg"'

En utilisant parallèle

parallel convert '{}' '{.}.jpg' ::: *.png
0
SergioAraujo