Que tal algo como isto no bash:
for file in ABC.*; do cp "$file" "${file/ABC/DEF}";done
você pode testá-lo colocando echo na frente do comando cp:
for file in ABC.*; do echo cp "$file" "${file/ABC/DEF}";done
Eu tenho uma pasta com vários arquivos nela ABC. * (existem cerca de 100 desses arquivos). Eu quero duplicar todos eles para novos arquivos com nomes começando com DEF. *
Então, eu quero
ABC.Page1
ABC.Page2
ABC.Topic12
...etc
copiado para
DEF.Page1
DEF.Page2
DEF.Topic12
...etc
Qual é a maneira mais simples de fazer isso com um comando em lote (em BASH ou similar)? Estou pensando em algo que envolve sed ou awk ou xargs, mas estou tendo dificuldade em descobrir a sintaxe. Eu poderia escrever um script Python, mas estou pensando que provavelmente existe uma solução de linha de comando que não é muito complicada.
Para fazer isso de maneira eficiente com um grande número de arquivos, é melhor evitar iniciar um processo cp
diferente para cada um. Uma maneira seria copiar e renomeá-las usando prename
( rename
é linkado por padrão para isto em distribuições baseadas em Debian). Usando isso e o Linux mktemp
:
tmp=$(mktemp -d --tmpdir=.)
cp ABC.* "$tmp"
prename "s:$tmp/ABC:DEF:" "$tmp/"*
rmdir "$tmp"
Na verdade, pax
pode ser o melhor caminho a seguir:
pax -rws '/^ABC/DEF/' ABC.* .
Infelizmente, apesar de o pax
ser tanto o POSIX quanto o Linux Standard Base, algumas distribuições atualmente o incluem por padrão.
Se você não se importa em usar uma ferramenta menos padrão, recomendo usar mmv (movimento em massa), que foi escrito para este tipo de tarefas. Usando mcp
(cópia em massa), que faz parte da suíte, você poderia simplesmente fazer
mcp "ABC.*" "DEF.#1"
Não é exatamente fácil encontrar pacotes de download. O pacote Debian atual (que o Arch também usa no AUR) para compilar em casa pode ser encontrado aqui .
tar
fará isso para você realmente rápido.
Primeiro eu criei 2 diretórios e 10 arquivos:
% 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
Então copiei:
% 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
Portanto, o% GNUtar
aceitará sed --transform=EXPRESSION
para renomear o arquivo. Isso pode até mesmo renomear apenas alguns dos arquivos. Por exemplo:
% tar -cf - ./* |\
tar -C../test2 --transform='s/ABC\(.*[0-5]\)/DEF/' -xf -
% ls ../test2
> ABC.file6 ABC.file8 DEF.file1 DEF.file2 DEF.file4
> ABC.file7 ABC.file9 DEF.file10 DEF.file3 DEF.file5
Então essa é uma vantagem.
Considere também que são apenas dois tar
processos - e isso não será alterado, independentemente da sua contagem de arquivos.
tar | tar
tar
é o mais otimizado possível. Isso nunca terá contagens de argumentos problemáticos ou processos filho fugitivos. Isso é apenas A > B concluído.
Eu uso 7 argumentos distintos combinados entre os meus dois processos tar
aqui. O mais importante está listado aqui primeiro:
-
stdout/stdin - this informstar
that it will be streaming either its input or output to or fromstdin/stdout
which it will interpret correctly depending on whether or not it is building or extracting an archive.
-c
create - this tellstar
to build the archive. The next argumenttar
expects is...
-f
file - we specify thattar
will be working with afile
object rather than a tape-device or whatever. And the file it will be working with, as noted above, isstdin/stdout
- in other words, our|pipe
.
./*
all $PWD/files - not too much to explain here except that the archive argument comes first, so-
then./*
.
... e do outro lado do |pipe
...
-C
change directory - this informstar
that it needs to change to the directory I specify before performing any other action, so effectively it justcd ../test2
before extraction.
--transform='s/ed/EXPR/'
- as has already been mentioned, this did the renaming. But the docs indicate that it can take anysed
expression or//flag
.
-x
extract - aftertar
changes to our target directory and receives our renaming instructions we instruct it to begin extracting all of the files into its current directory from the-f - |pipe
archive file. No mystery.
Em zsh, insira as seguintes linhas no seu .zshrc
:
autoload -U zmv
alias zmv='noglob zmv'
alias zcp='zmv -C'
alias zln='zmv -L'
Em seguida, na linha de comando, você pode executar
zcp 'ABC(.*)' 'DEF$1'
ou simplesmente
zcp -W ABC.* DEF.*
Em outro shell, contanto que você tenha o zsh instalado:
zsh -c 'autoload zmv; noglob zmv -CW ABC.* DEF.*'
Você pode fazer isso:
for i in ABC.*; do cp {ABC,DEF}."${i#*.}"; done
Você pode fazer isso: link Aqui está o exemplo