Como copio vários arquivos por caractere curinga?

33

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.

    
por Octopus 01.04.2014 / 20:33

7 respostas

33

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
    
por 01.04.2014 / 20:39
7

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"

Atualizar

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.

    
por 01.04.2014 / 21:13
5

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 .

    
por 01.04.2014 / 23:24
5

tar fará isso para você realmente rápido.

TESTE

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

TRANSFORMAR

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.

STREAM

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.

ARGUMENTOS

Eu uso 7 argumentos distintos combinados entre os meus dois processos tar aqui. O mais importante está listado aqui primeiro:

- stdout/stdin - this informs tar that it will be streaming either its input or output to or from stdin/stdout which it will interpret correctly depending on whether or not it is building or extracting an archive.

-c create - this tells tar to build the archive. The next argument tar expects is...

-f file - we specify that tar will be working with a file object rather than a tape-device or whatever. And the file it will be working with, as noted above, is stdin/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 informs tar that it needs to change to the directory I specify before performing any other action, so effectively it just cd ../test2 before extraction.

--transform='s/ed/EXPR/' - as has already been mentioned, this did the renaming. But the docs indicate that it can take any sed expression or //flag.

-x extract - after tar 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.

    
por 02.04.2014 / 12:55
2

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.*'
    
por 02.04.2014 / 01:18
1

Você pode fazer isso:

for i in ABC.*; do cp {ABC,DEF}."${i#*.}"; done
    
por 01.04.2014 / 21:30
-1

Você pode fazer isso: link Aqui está o exemplo

    
por 22.07.2014 / 18:16