Renommer les fichiers par lots en ligne de commande et Xargs

j'ai Donc 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, Comment puis-je renommer le fichier de sorte que je ne puisse avoir qu'une extension. Pas deux. (en gros, comment je nettoie mon erreur d'origine)?



La deuxième question est, à l'avenir, d'utiliser xargs, Comment puis-je changer l'extension du fichier simular en second command?

19
demandé sur Tim Pote 2012-06-11 00:13:26

6 réponses

Comment puis-je renommer le fichier pour que je ne puisse avoir qu'une extension.

cd dir/with/messedup/files

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

dans l'avenir, en utilisant xargs, comment puis-je changer l'extension du fichier similaires à la deuxième commande?

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

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

Si vous avez des fichiers dans des sous-répertoires que vous voulez convertir, puis vous pouvez pipe findwhile read boucle:

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

NOTE: c'est généralement considéré comme un mauvaise idée pour utiliser la sortie de ls dans un script shell. Bien que votre exemple ait peut-être bien fonctionné, il y a beaucoup d'exemples où il n'a pas fonctionné. Par exemple, si vos noms de fichiers contiennent des newlines (ce que permet unix),ls n'échappera probablement pas à ceux-là pour vous. (Cela dépend en fait de votre mise en œuvre, 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 find dans un tout-lecture en boucle ou d'un fichier d'expansion (par exemple,*.png) dans une boucle for.

18
répondu Tim Pote 2012-06-10 20:35:30

cela peut aussi ê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. Puis xargs utilise ces deux arguments dans la commande move. Pour la doublure, j'ai aussi ajouté un grep pour filtrer tout ce qui n'est pas un *.fichier png.

44
répondu Schleis 2013-10-15 14:50:41

fin de la partie, mais voici comment vous pouvez renommer les fichiers avec xargs. Disons que vous avez un tas de fichiers nommés fileN.svg.png et vous voulez les appeler 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 enlever les deux .svg et .png pour obtenir une juste filenameN. Le second xargs reçoit ce nom nu et utilise le remplacement pour renommer le fichier.

9
répondu Dethe 2015-05-09 06:20:41

pour corriger votre erreur, essayez le rename utilitaire. Vérifiez la page de manuel pour plus de détails.

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

Puisque vous avez convert disponible, je suppose que vous avez mogrify (imagemagick suite). Chaque fois que je veux faire cela, je copie les fichiers dans un répertoire différent et j'utilise mogrify à la place. Je n'en ai généralement besoin que pour redimensionner, mais si vous changez le format de l'image aussi, mogrify va gérer le noms de fichiers (créer de nouveaux fichiers avec les noms de fichiers appropriés).

vous l'utiliseriez comme mogrify -format jpg -resize [size] ./*.png. Je ne suis pas sûr de ce que -resize sans arguments de géométrie est censé faire l'affaire. Il n'est pas documentée et ne fonctionne pas sur ma machine.

comme le raisonnait Tim Pote, je ne pense pas que vous puissiez faire des xargs traiter les noms de fichiers et les extensions séparément.

6
répondu Matej 2012-06-10 21:14:31

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

j'ai d'abord converti en faisant:

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

ce Qui bien sûr conduit à la même question, comme 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 *.png, c'est ce que j'ai fini par faire...

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. trouvez dans ce répertoire les fichiers nommés *.svg.png, le-print0 imprime à la sortie standard
  2. sed modifie la sortie standard, essentiellement l'échange .svg.png avec rien, donc j'aimerais obtenir: fichier1/fichier2/fichier3/fichier4
  3. xargs -0 pour obtenir les données à partir de sed, -je renvoie le nom du fichier avec l'extension, puis mv nom du fichier original à nouveau nom du fichier. Le mot namePrefix n'est pas quelque chose de spécial, je voulais juste le faire clair.

EDIT

je me rends compte maintenant que c'est la façon la plus alambiquée de le faire. On peut simplement utiliser la commande renommer.

rename 's/svg\.png/.png/' *
3
répondu Paul J 2017-01-22 08:08:14

ma solution est similaire à de nombreuses solutions xarg, et particulièrement similaire à celle de Schleis.

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

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

Modifier dans le remplacement de n'importe quel extension.

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

Explication

-n arg dire sed à ne pas effectuer d'impression par défaut, le T commande dit passez à la fin du script si la précédente s le commandement n'a pas fait de remplacement, le p la commande affiche l'espace de motif (seulement si le s correspond à la commande).

& dans le remplacement est une référence au contenu de la nom de fichier original de match.

si nous remplaçons mv dans la commande bash -c 'echo "run($#) $@"' bash ensuite, nous pouvons voir le nombre de fois mv serait appelé, et avec le nombre et la valeur des paramètres:

$ ls |
  sed -nE 's/Rick\.and\.Morty\.(S03E[0-9]{2})\..*(\.[a-z0-9]{3})/"&" "Rick and Morty "/;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
0
répondu joshperry 2018-02-17 20:23:20