Existe-t-il une commande linux comme mv mais avec regex?

39

Par exemple je veux mv (.*?).sql $1.php,

Existe-t-il une commande qui me permet de spécifier des modèles de changement de nom?

JoshRibs
la source

Réponses:

32

Comme d’autres l’ont déjà mentionné, renamec’est bon, mais lisez la page de manuel ( man rename) avant de l’essayer. Il existe au moins deux outils totalement différents qui s'appellent, renameet celui que vous avez dépendra de votre distribution. Les appeler incorrectement peut être dangereux.

Voici la page de manuel de la version basée sur perl de Larry Wall fournie avec Ubuntu. Vous lui donnez une expression perl commerename 's/\.sql$/.php/' *.sql

Voici la page de manuel relative au changement de nom fourni avec les anciennes distributions Red Hat et CentOS. L'utilisation est simple substitution de chaîne commerename .sql .php *.sql

Vous pouvez également utiliser une ligne simple pour traiter chaque fichier un à la fois:

$ for f in *.sql; do mv -i "$f" "${f%%.*}.php"; done
Ryan Bright
la source
Quelqu'un pourrait-il télécharger un fichier binaire Windows pour le changement de nom basé sur Perl?
Marcandre
La version renommée de Perl ne peut pas déplacer des fichiers d’un système de fichiers à un autre.
lilydjwg
bash one-liner est utile, surtout en l'absence de renamefonction (par exemple, busybox).
Artm
10

Il y a rename(1), qui n'utilise pas de regex, mais peut résoudre votre problème:

rename .sql .php *.sql

Il y a aussi mmv(1), mais je ne connais pas comment ça marche.

Adam Rosenfield
la source
Dans Ubuntu et Debian (pas sûr des autres distributions), /usr/bin/renameliens vers /usr/bin/prenamepar défaut, ce qui prend les expressions rationnelles.
aphink
5

G'day

Vous pouvez également essayer d'entrer

for i in $(\ls -d *.sql)
do
mv $i $(echo $i | sed -e 's/\.sql$/\.php/')
done

Ou pour le faire utiliser regex changer légèrement

for i in $(\ls -d | egrep -e '.*\.sql')
do
mv $i $(echo $i | sed -e 's/\.sql$/\.php/')
done

pour un peu d'amusement de codage de shell. (-:

Rob Wells
la source
2
Cela échoue avec les fichiers contenant des espaces dans leur nom, soyez donc prudent. Il nels faut jamais analyser la sortie .
slhck
L' sedexemple est assez bon, cependant.
étoile brillante
2

En tant que plombier, j'aime les pipes :)

Remarque: cette réponse est détaillée - en tant que débutant, je l’apprécie lorsque quelqu'un qui sait prend le temps de l'expliquer, je paie donc «en avant». Si vous n'êtes pas un débutant, veuillez excuser la longueur et la verbosité.

ls -1 *_201[67][0-9]* | sed -e 's/\(\(.\+\)[-_]\(201[67][0-9]\{4\}\)\([^.]\+\)\?\.[0-9a-z]\{2,3\}\)/mkdir -p \2\/\3; mv \1 \2\/\3\/\1/' | bash

Où:

ls -1 *_201[67][0-9]*

liste tous les fichiers correspondant au modèle, dans ce cas, je recherche des fichiers avec la date dans le nom du fichier sous la forme 'AAAAMMJJ'

sed -e 's/\(\(.\+\)[-_]\(201[67][0-9]\{4\}\)\([^.]\+\)\?\.[0-9a-z]\{2,3\}\)/mkdir -p \2\/\3; mv \1 \2\/\3\/\1/'
#        : | |    |     |                  | |       |                    |:                                 :
#        : |^2....^    ^3..................^^4.......^                    |:                                 :
#        :^1..............................................................^:                                 :
#        /................filename.................pattern................./...mkdir...and....mv...command.../

^ 1: 1er groupe de capture - le nom de fichier complet

^ 2: 2e groupe de capture - la 1ère partie du motif de nom de fichier

^ 3: 3ème groupe de capture - la 2ème partie du nom de fichier - ici, la date sous la forme 'AAAAMMJJ'

^ 4: 4ème groupe de capture - partie de nom de fichier facultative située entre la date et l'extension, et l'extension elle-même

Sooooo .... si j'ai un fichier nommé

CallLog_555123412_20161231-214403.7z

...ensuite

mkdir -p \2\/\3; mv \1 \2\/\3\/\1

signifie en réalité

# make directory and sub-directory
mkdir -p CallLog_555123412/20161231
# move file from current directory to sub-sub-directory just created
mv CallLog_555123412_20161231-214403.7z CallLog_555123412/20161231/CallLog_555123412_20161231-214403.7z

Notez que la sortie de la commande sed est acheminée vers "bash" pour l'exécuter. Pour voir d’abord les mouvements de fichier proposés SANS les déplacer réellement, commencez par supprimer le '| bash 'à la fin, et essayez comme ça:

ls -1 *_201[67][0-9]* | sed -e 's/\(\(.\+\)[-_]\(201[67][0-9]\{4\}\)\([^.]\+\)\?\.[0-9a-z]\{2,3\}\)/mkdir -p \2\/\3; mv \1 \2\/\3\/\1/'

Cela ne fera aucun changement, mais vous verrez la commande qui sera exécutée SI vous l'exécutez avec '| bash 'tagué à la fin.

Cela est utile car vous pouvez créer les sous-répertoires de votre choix à partir de parties du nom de fichier, ou de tout autre élément ajouté au texte de remplacement dans la commande sed. Notez que sed nécessite cependant beaucoup de caractères d'échappement.

Supports SED Regex:

(...) nécessite un échappement pour le regroupement des captures -> \ (... \)

{m, n} nécessite un échappement pour quantifier l'objet précédent -> \ {m, n \}

/ nécessite d'échapper dans la chaîne de remplacement -> \ /

[...] NE PAS obliger à s'échapper pour les classes de personnage

\ 1 dans la chaîne de remplacement fait référence au 1er groupe capturé, et ainsi de suite ...

AVERTISSEMENT DE SÉCURITÉ: NE JAMAIS PIPE RIEN DE 'BASSER' SAUF SI VOUS COMPRENEZ COMPLÈTEMENT LE RÉSULTAT ...

J'espère que cela aidera à éliminer certains blocages :)

skeetastax
la source
1

Installez mmv, puis faites ceci:

mmv "*.sql" "#1.php"
Gepsens
la source