Objectif
Modifiez ces noms de fichiers:
- F00001-0708-RG-biasliuyda
- F00001-0708-CS-akgdlaul
- F00001-0708-VF-hioulgigl
à ces noms de fichiers:
- F0001-0708-RG-biasliuyda
- F0001-0708-CS-akgdlaul
- F0001-0708-VF-hioulgigl
Code Shell
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 commande de substitution
$ 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 simplement à cela: "un seul caractère, suivi d'un seul caractère, suivi de toute séquence de longueur d'un seul caractère" - 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.
bash
shell
sed
file-rename
Daniel Underwood
la source
la source
Réponses:
Tout d'abord, je dois dire que le moyen le plus simple de le faire est d'utiliser les commandes prename ou renommer.
Sur Ubuntu, OSX (package Homebrew, package
rename
MacPortsp5-file-rename
) ou d'autres systèmes avec un renommage perl (prename):ou sur les systèmes renommés de util-linux-ng, tels que RHEL:
C'est beaucoup plus compréhensible que la commande sed équivalente.
Mais pour comprendre la commande sed, la page de manuel sed est utile. Si vous exécutez man sed et recherchez & (en utilisant la commande / pour rechercher), vous trouverez qu'il s'agit d'un caractère spécial dans s / foo / bar / remplacements.
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
. Puis.
correspond au caractère suivant, qui est toujours 0. Puis\(.*\)
correspond au reste du nom de fichier, qui peut être référencé par\2
.La chaîne de remplacement met tout cela ensemble en utilisant
&
(le nom de fichier d'origine) et\1\2
qui est chaque partie du nom de fichier à l'exception du 2ème caractère, qui était un 0.C'est une façon assez cryptique de faire cela, à mon humble avis. Si pour une raison quelconque la commande renommer n'était pas disponible et que vous vouliez utiliser sed pour faire le changement de nom (ou peut-être que vous faisiez quelque chose de trop complexe pour renommer?), Être plus explicite dans votre regex la rendrait beaucoup plus lisible. Peut-être quelque chose comme:
ls F00001-0708-*|sed 's/F0000\(.*\)/mv & F000\1/' | sh
Être capable de voir ce qui change réellement dans le s / search / replacement / le rend beaucoup plus lisible. De plus, il ne continuera pas à aspirer les caractères de votre nom de fichier si vous l'exécutez accidentellement deux fois ou quelque chose du genre.
la source
rename
soit lui-même un "renommé" lien . ierename
a été "renommé" deprename
.. par exemple, dans Ubuntu:readlink -f $(which rename)
sorties/usr/bin/prename
... Lerename
mentionné par David est un programme entièrement différent.sh
? ceci est potentiellement dangereux car du code arbitraire peut être exécuté (vous traitez les données comme du code).vous avez eu votre explication sed, maintenant vous pouvez utiliser uniquement le shell, pas besoin de commandes externes
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
la source
J'ai écrit un petit article avec des exemples sur le changement de nom par lots en utilisant
sed
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 comme\1\
,\2
etc.la source
Le moyen le plus simple serait:
for i in F00001*; do mv "$i" "${i/F00001/F0001}"; done
ou, portatif,
for i in F00001*; do mv "$i" "F0001${i#F00001}"; done
Cela remplace le
F00001
préfixe dans les noms de fichiers parF0001
. crédits à mahesh ici: http://www.debian-administration.org/articles/150la source
mv "$i" "${i/F00001/F0001}"
. Mais +1La
sed
commandesignifie remplacer:
avec:
comme une
sed
commande ordinaire . Cependant, les parenthèses&
et les\n
marqueurs le changent un peu.La chaîne de recherche correspond (et se souvient comme motif 1) du caractère unique au début, suivi d'un seul caractère, suivi du reste de la chaîne (mémorisé comme motif 2).
Dans la chaîne de remplacement, vous pouvez faire référence à ces modèles correspondants pour les utiliser dans le cadre du remplacement. Vous pouvez également faire référence à toute la partie correspondante comme
&
.Donc, ce que
sed
fait cette commande est de créer unemv
commande basée sur le fichier d'origine (pour la source) et les caractères 1 et 3 en avant, supprimant effectivement le caractère 2 (pour la destination). Il vous donnera une série de lignes selon le format suivant:etc.
la source
ls | sed "s/\(.\).\(.*\)/mv & \1\2/" | bash
ls
, tuyau à traverssed
et conduit ensuite à travers une coquille! il est soumis à l'exécution de code arbitraire avec des noms de fichiers falsifiés. Le problème est que les données doivent être traitées comme des données, et ici, elles sont généralement sérialisées en code sans aucune précaution. Je souhaite que paxdiablo puisse supprimer cette réponse car elle ne montre vraiment pas de bonnes pratiques. (Je suis tombé sur cette question parce qu'un débutant a lancé au hasard| sh
une commande qui n'a pas fonctionné et après avoir vu cette question et les réponses ont pensé que cela fonctionnerait mieux - je suis horrifié!):)
.Le truc de backslash-paren signifie, "tout en faisant correspondre le modèle, gardez le truc qui correspond ici." Plus tard, du côté du texte de remplacement, vous pouvez récupérer ces fragments mémorisés avec "\ 1" (premier bloc entre parenthèses), "\ 2" (deuxième bloc), et ainsi de suite.
la source
Si tout ce que vous faites vraiment est de supprimer le deuxième caractère, quel qu'il soit, vous pouvez le faire:
mais votre commande construit une
mv
commande et la transmet au 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 il
find
ajoute «./» à chaque nom de fichier.la source
| sh
suivent au hasard une commande qui ne fonctionne pas, dans l'espoir que cela fonctionnera mieux. C'est horrible! (et en plus, ce n'est pas une bonne pratique). J'espère que vous comprendrez!Les parenthèses capturent des chaînes particulières à utiliser par les nombres avec une barre oblique inverse.
la source
ls F00001-0708-*|sed 's|^F0000\(.*\)|mv & F000\1|' | bash
la source
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
Ensuite, si cela semble correct, ajoutez
| sh
à la fin. Donc: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
la source
Utilisation du renommage perl ( indispensable dans la boîte à outils):
rename -n 's/0000/000/' F0000*
Retirez le
-n
commutateur lorsque la sortie semble bonne pour le renommer pour de vrai.Il existe d'autres outils portant le même nom qui peuvent ou non être en mesure de le faire, alors soyez prudent.
La commande renommer qui fait partie de la
util-linux
package ne le fera pas.Si vous exécutez la commande suivante (
GNU
)et tu vois
perlexpr
, alors cela semble être le bon outil.Sinon, pour en faire la valeur par défaut (généralement déjà le cas) sur
Debian
et dérivé commeUbuntu
:$ sudo apt install rename $ sudo update-alternatives --set rename /usr/bin/file-rename
Pour archlinux:
Pour les distributions de la famille RedHat:
Le package 'prename' se trouve dans le référentiel EPEL .
Pour Gentoo:
Pour * BSD:
ou
p5-File-Rename
Pour les utilisateurs Mac:
Si vous n'avez pas cette commande avec une autre distribution, recherchez votre gestionnaire de paquets pour l'installer ou faites-le manuellement :
L'ancienne version autonome peut être trouvée ici
homme renommer
Cet outil a été à l'origine écrit par Larry Wall, le père de Perl.
la source
for i in *; do mv $i $(echo $i|sed 's/AAA/BBB/'); done
la source