Objectif
Changer ces noms de fichiers:
à ces noms de fichiers:
Shell Code
Tester:
ls F00001-0708-*|sed 's/\(.\).\(.*\)/mv & \1\2/'
Pour effectuer:
ls F00001-0708-*|sed 's/\(.\).\(.*\)/mv & \1\2/' | sh
Ma question
Je ne comprends pas le code sed. Je comprends ce que la substitution Commande
$ sed 's/something/mv'
veux dire. Et je comprends un peu les expressions régulières. Mais je ne comprends pas ce qui se passe ici:
\(.\).\(.*\)
ou ici:
& \1\2/
Le premier, pour moi, ressemble à cela signifie: "un seul caractère, suivi par un seul caractère, suivi de toute séquence de longueur d'un caractère unique " - mais il y a sûrement plus que cela. En ce qui concerne La dernière partie:
& \1\2/
Je n'ai aucune idée. Je veux vraiment comprendre ce code. S'il vous plaît, aidez-moi, ici, les gars.
Premièrement, je devrais dire que le moyen le plus simple de procéder consiste à utiliser les commandes Prename ou à renommer.
Sous Ubuntu, OSX (paquet Homebrew rename
, paquet MacPorts p5-file-rename
) ou d’autres systèmes avec renom Perl (prename):
rename s/0000/000/ F0000*
ou sur des systèmes renommés depuis util-linux-ng, tels que RHEL:
rename 0000 000 F0000*
C'est beaucoup plus compréhensible que la commande sed équivalente.
Mais pour ce qui est de comprendre la commande sed, la page de manuel sed est utile. Si Vous lancez man sed et recherchez & (en utilisant la commande/pour rechercher), Vous constaterez que c'est un caractère spécial dans s/foo/bar/replacements.
s/regexp/replacement/
Attempt to match regexp against the pattern space. If success‐
ful, replace that portion matched with replacement. The
replacement may contain the special character & to refer to that
portion of the pattern space which matched, and the special
escapes \1 through \9 to refer to the corresponding matching
sub-expressions in the regexp.
Par conséquent, \(.\)
correspond au premier caractère, qui peut être référencé par \1
. Ensuite, .
correspond au caractère suivant, qui est toujours 0 . Ensuite, \(.*\)
correspond au reste du nom de fichier, qui peut être référencé par \2
.
La chaîne de remplacement assemble le tout en utilisant &
(le fichier Nomfichier d'origine) et \1\2
, qui représente toutes les parties du nom de fichier, sauf le 2e caractère , Qui était un 0.
Ceci est une façon assez cryptique de le faire, à mon humble avis. Si, pour une raison quelconque, la commande renommer n’était pas disponible et que vous vouliez utiliser Sed pour renommer (ou peut-être que vous faisiez quelque chose de trop complexe Pour renommer?), Être plus explicite dans votre regex le rendre beaucoup plus lisible. Peut-être quelque chose comme:
ls F00001-0708-*|sed 's/F0000\(.*\)/mv & F000\1/' | sh
Etre capable de voir ce qui change réellement dans le fichier S/search/replacement/le rend beaucoup plus lisible. En outre, il ne gardera pas les caractères sucer hors de votre nom de fichier si vous le lancez accidentellement .__ deux fois ou quelque chose du genre.
vous avez eu votre explication sed, maintenant vous pouvez utiliser uniquement le shell
for file in F0000*
do
echo mv "$file" "${file/#F0000/F000}"
# ${file/#F0000/F000} means replace the pattern that starts at beginning of string
done
J'ai écrit un petit article avec des exemples sur le renommage par lots en utilisant sed
il y a quelques années:
http://www.guyrutenberg.com/2009/01/12/batch-renaming-using-sed/
Par exemple:
for i in *; do
mv "$i" "`echo $i | sed "s/regex/replace_text/"`";
done
Si l'expression régulière contient des groupes (par exemple \(subregex\
), vous pouvez les utiliser dans le texte de remplacement en tant que \1\
, \2
etc.
Le moyen le plus simple serait:
for i in F00001*; do mv "$i" "${i/F00001/F0001}"; done
ou, de manière portable,
for i in F00001*; do mv "$i" "F0001${i#F00001}"; done
Ceci remplace le préfixe F00001
dans les noms de fichiers par F0001
. Crédits à mahesh ici: http://www.debian-administration.org/articles/150
La commande sed
s/\(.\).\(.*\)/mv & \1\2/
moyens de remplacer:
\(.\).\(.*\)
avec:
mv & \1\2
comme une commande sed
normale. Cependant, les marqueurs entre parenthèses, &
et \n
le changent un peu.
La chaîne de recherche correspond (et mémorise en tant que motif 1) au caractère unique au début, suivi d'un seul caractère suivi du reste de la chaîne (mémorisée en tant que motif 2).
Dans la chaîne de remplacement, vous pouvez vous référer à ces modèles correspondants pour les utiliser dans le cadre du remplacement. Vous pouvez également vous référer à la partie correspondante sous la forme &
.
Ainsi, la commande sed
crée une commande mv
basée sur le fichier d'origine (pour la source) et les caractères 1 et 3, en supprimant le caractère 2 (pour la destination). Il vous donnera une série de lignes selon le format suivant:
mv F00001-0708-RG-biasliuyda F0001-0708-RG-biasliuyda
mv abcdef acdef
etc.
Le terme "backslash-paren" signifie "tout en respectant le motif, conservez le contenu correspondant". Plus tard, du côté du texte de remplacement, vous pouvez récupérer ces fragments avec "\ 1" (premier bloc entre parenthèses), "\ 2" (deuxième bloc), etc.
Voici ce que je ferais:
for file in *.[Jj][Pp][Gg] ;do
echo mv -vi \"$file\" `jhead $file|
grep Date|
cut -b 16-|
sed -e 's/:/-/g' -e 's/ /_/g' -e 's/$/.jpg/g'` ;
done
Si cela vous convient, ajoutez | sh
à la fin. Alors:
for file in *.[Jj][Pp][Gg] ;do
echo mv -vi \"$file\" `jhead $file|
grep Date|
cut -b 16-|
sed -e 's/:/-/g' -e 's/ /_/g' -e 's/$/.jpg/g'` ;
done | sh
Les parenthèses capturent des chaînes particulières à utiliser par les nombres inversés.
ls F00001-0708-*|sed 's|^F0000\(.*\)|mv & F000\1|' | bash
Si tout ce que vous faites, c'est supprimer le deuxième caractère, peu importe sa nature, vous pouvez le faire:
s/.//2
mais votre commande est en train de construire une commande mv
et de la diriger vers le shell pour exécution.
Ce n'est pas plus lisible que votre version:
find -type f | sed -n 'h;s/.//4;x;s/^/mv /;G;s/\n/ /g;p' | sh
Le quatrième caractère est supprimé car find
ajoute chaque nom de fichier avec "./".