J'ai un répertoire appelé "images" rempli d'environ un million d'images. Oui. P>
Je veux écrire une commande shell pour renommer toutes ces images dans le format suivant: P>
Original: i> Toute suggestion? P>
merci, FileName.jpg code>
Nouveau: i> /f/i/l/filename.jpg code> p>
Dan p>
5 Réponses :
Vous pouvez générer le nouveau nom de fichier à l'aide, par exemple, SED:
#!/usr/bin/perl -w use strict; # warning: untested opendir DIR, "." or die "opendir: $!"; my @files = readdir(DIR); # can't change dir while reading: read in advance closedir DIR; foreach my $f (@files) { (my $new_name = $f) =~ s!^((.)(.)(.).*)$!$2/$3/$4/$1/; -e $new_name and die "$new_name already exists"; rename($f, $new_name); }
Oh, je remarque une chose que les tests auraient trouvé: il faut un test "Est-ce un fichier?" Donc, cela ne déplace pas les répertoires. Assez facile à réparer (par exemple, -f $ f ou suivant; code> en haut de la boucle de Perl foreach, similaire dans la boucle de coquille)
Je suggère un bref script Python. La plupart des outils Shellberont à majorité à cette contribution (bien que Xargs puissent faire l'affaire). Mettra à jour avec l'exemple dans une seconde.
#!/usr/bin/python import os, shutil src_dir = '/src/dir' dest_dir = '/dest/dir' for fn in os.listdir(src_dir): os.makedirs(dest_dir+'/'+fn[0]+'/'+fn[1]+'/'+fn[2]+'/') shutil.copyfile(src_dir+'/'+fn, dest_dir+'/'+fn[0]+'/'+fn[1]+'/'+fn[2]+'/'+fn)
Merci, ressemble à une solution merveilleuse. J'ai besoin d'attendre que les fichiers se transfèrent sur mon nouveau serveur avant de pouvoir l'essayer (ETA 50 heures lol)
for i in *.*; do mkdir -p ${i:0:1}/${i:1:1}/${i:2:1}/; mv $i ${i:0:1}/${i:1:1}/${i:2:1}/; done; The ${i:0:1}/${i:1:1}/${i:2:1} part could probably be a variable, or shorter or different, but the command above gets the job done. You'll probably face performance issues but if you really want to use it, narrow the *.* to fewer options (a*.*, b*.* or what fits you)edit: added a $ before i for mv, as noted by Dan
FYI, le $ {i: 0: 1} code> Syntaxe est un ism Bash-ism, qui est probablement OK sur Linux, mais juste au cas où ...
S'il y a quelques répertoires dans le dossier, cette boucle les inclurea-t-elle aussi?
Besoin d'une correction: car je dans . I>; do mkdir -p $ {i: 0: 1} / $ {i: 1: 1} / $ {i: 2: 1} /; mv $ i $ {i: 0: 1} / $ {i: 1: 1} / $ {i: 2: 1} /; terminé;
Seuls les répertoires avec des points en eux!
Dans mon cas, j'ai besoin de créer et de déplacer des fichiers vers un répertoire portant les sept premiers caractères du nom de fichier. Quelque chose comme FOO01, FOO02, FOO03 à la répertoire FOO; et BAR01, BAR02 à la barre d'annuaire. J'ai remplacé $ {i: 0: 1} / $ {i: 1: 1} / $ {i: 2: 1} / code> pour
$ {i: 0: 7} / < / code> et cela a fonctionné comme un charme.
Vous pouvez le faire sous forme de script Bash:
#!/bin/bash base=base mkdir -p $base/shorts for n in * do if [ ${#n} -lt 3 ] then mv $n $base/shorts else dir=$base/${n:0:1}/${n:1:1}/${n:2:1} mkdir -p $dir mv $n $dir fi done
L'une des solutions proposées qui utilisent une syntaxe Wildcard dans la coquille échouera probablement en raison du nombre de fichiers dont vous disposez. Parmi les solutions proposées actuelles, le Perl One est probablement le meilleur.
Cependant, vous pouvez facilement adapter les méthodes de script shell pour traiter n'importe quel nombre de fichiers ainsi: P>
ls -1 | \ while read filename do # insert the loop body of your preference here, operating on "filename" done
La syntaxe Wildcard devrait être bien, sa coquille intégrée et sa non-transmission de la ligne de commande à un programme exprès (sinon, sûrement, la ligne de commande serait trop longue). Pour i dans SEQ 1 1000000 code> fonctionne, par exemple.
Je viens de tester: utiliser pour f in * code> fonctionne parfaitement avec 1 000 000 fichiers. Lent, mais ça marche.
Merci pour votre commentaire, il était utile que je suis très nouveau dans les scripts shell
@derobert: Merci d'avoir testé cela et confirmant que fait i> travaille. Ceci est apparemment un cas où les leçons tirées des vieux jours ne sont pas nécessairement vraies. Bash apparemment amélioré cet aspect. Je sais pour un fait qu'il a échoué de différentes manières sous la coquille de Bourne, mais qui était de retour à la fin des années 80 / début des années 90 lorsque j'ai commis une erreur lors de la rédaction d'un script pour effectuer une maintenance sur les annuaires NetNews.