J'ai un dossier contenant un certain nombre de fichiers ABC. * (Il y a environ 100 fichiers de ce type). Je veux les dupliquer tous dans de nouveaux fichiers avec des noms commençant par DEF. *
Donc je veux
ABC.Page1
ABC.Page2
ABC.Topic12
...etc
copié dans
DEF.Page1
DEF.Page2
DEF.Topic12
...etc
Quelle est la manière la plus simple de le faire avec une commande batch (en BASH ou similaire)? Je pense à quelque chose impliquant sed ou awk ou xargs, mais j'ai du mal à trouver la syntaxe. Je pourrais écrire un script Python, mais je pense qu'il existe probablement une solution en ligne de commande qui n'est pas trop compliquée.
Que diriez-vous de quelque chose comme ça dans bash:
for file in ABC.*; do cp "$file" "${file/ABC/DEF}";done
vous pouvez le tester en mettant echo devant la commande cp:
for file in ABC.*; do echo cp "$file" "${file/ABC/DEF}";done
Pour le faire efficacement avec un grand nombre de fichiers, il vaut mieux éviter de démarrer un processus cp
différent pour chacun. Une façon serait de les copier puis de les renommer en utilisant prename
(rename
est lié à ceci par défaut sur les distributions basées sur Debian). En utilisant ceci et Linux mktemp
:
tmp=$(mktemp -d --tmpdir=.)
cp ABC.* "$tmp"
prename "s:$tmp/ABC:DEF:" "$tmp/"*
rmdir "$tmp"
En fait, pax
peut être une meilleure façon d'aller ici:
pax -rws '/^ABC/DEF/' ABC.* .
Malheureusement, bien que pax
soit à la fois POSIX et Linux Standard Base, peu de distributions l'incluent actuellement par défaut.
tar
le fera pour vous très rapidement.
J'ai d'abord créé 2 répertoires et 10 fichiers:
% mkdir test1 test2 ; cd test1
% for n in `seq 1 10` ; do touch ABC.file$n ; done
% ls
> ABC.file1 ABC.file2 ABC.file4 ABC.file6 ABC.file8
> ABC.file10 ABC.file3 ABC.file5 ABC.file7 ABC.file9
Ensuite, je les ai copiés:
% tar -cf - ./* |\
tar -C../test2 --transform='s/ABC/DEF/' -xf -
% ls ../test2
> DEF.file1 DEF.file2 DEF.file4 DEF.file6 DEF.file8
> DEF.file10 DEF.file3 DEF.file5 DEF.file7 DEF.file9
Donc GNU tar
acceptera un sed --transform=EXPRESSION
pour renommer un fichier. Cela peut même renommer seulement certains fichiers. Par exemple:
% tar -cf - ./* |\
tar -C../test2 --transform='s/ABC\(.*[0-5]\)/DEF\1/' -xf -
% ls ../test2
> ABC.file6 ABC.file8 DEF.file1 DEF.file2 DEF.file4
> ABC.file7 ABC.file9 DEF.file10 DEF.file3 DEF.file5
Voilà donc un avantage.
Considérez également qu'il ne s'agit que de deux processus tar
- et que cela ne changera pas quel que soit le nombre de fichiers.
tar | tar
tar
est aussi optimisé que vous le souhaiteriez. Cela n'aura jamais de nombre d'arguments problématiques ou de processus enfants incontrôlables. C'est juste A> B fait.
J'utilise ici 7 arguments distincts combinés entre mes deux processus tar
. Le plus important est répertorié ici en premier:
-
stdout/stdin - cela informetar
qu'il diffusera son entrée ou sa sortie vers ou depuisstdin/stdout
qu'il interprètera correctement selon qu'il construit ou extrait une archive.
-c
create - ceci indique àtar
de construire l'archive. L'argument suivant quetar
attend est ...
-f
file - nous spécifions quetar
fonctionnera avec un objetfile
plutôt qu'avec un lecteur de bande ou autre. Et le fichier avec lequel il va travailler, comme indiqué ci-dessus, eststdin/stdout
- en d'autres termes, notre|pipe
.
./*
tous $ PWD/fichiers - pas trop à expliquer ici sauf que l'argument archive vient en premier, donc-
puis./*
.
... et de l'autre côté du |pipe
...
-C
change directory - ceci informetar
qu'il doit changer dans le répertoire que je spécifie avant d'effectuer toute autre action, donc en fait il suffit decd ../test2
avant extraction.
--transform='s/ed/EXPR/'
- comme cela a déjà été mentionné, cela a fait le renommage. Mais les documents indiquent qu'il peut prendre n'importe quelle expressionsed
ou//flag
.
-x
extract - après quetar
ait changé notre répertoire cible et reçu nos instructions de changement de nom, nous lui demandons de commencer à extraire tous les fichiers dans son répertoire actuel à partir du-f - |pipe
fichier d'archive. Pas de mystère.
Si cela ne vous dérange pas d'utiliser un outil moins standard, je recommande d'utiliser mmv (mouvement de masse) qui a été écrit pour ce type de tâches. En utilisant mcp
(copie de masse), qui fait partie de la suite, vous pouvez simplement faire
mcp "ABC.*" "DEF.#1"
Il n'est pas vraiment facile de trouver des packages de téléchargement. Le paquet Debian actuel (qu'Arch utilise également dans AUR) pour compiler à la maison peut être trouvé ici .
Dans zsh, mettez les lignes suivantes dans votre .zshrc
:
autoload -U zmv
alias zmv='noglob zmv'
alias zcp='zmv -C'
alias zln='zmv -L'
Ensuite, sur la ligne de commande, vous pouvez exécuter
zcp 'ABC(.*)' 'DEF$1'
ou simplement
zcp -W ABC.* DEF.*
Dans un autre shell, tant que vous avez installé zsh:
zsh -c 'autoload zmv; noglob zmv -CW ABC.* DEF.*'
Vous pouvez faire ceci:
for i in ABC.*; do cp {ABC,DEF}."${i#*.}"; done