Como copiar arquivos cujo nome contenha números de 20 a 32

5

Eu quero copiar arquivos de copyDest para pastDest que contenham números de 20 a 32. O que estou errado?

cp -r ~/copyDest/*2[0-9]|3[0-2]* ~/pasteDest

Obrigado.

    
por user317427 24.10.2018 / 10:37

5 respostas

9

| é o operador de pipeline.

cp -r ~/copyDest/*2[0-9]|3[0-2]* ~/pasteDest

é o comando cp canalizado para o comando cujo nome é o primeiro arquivo expandido do 3[0-2]* glob. Para | ser um operador de alternação glob, ele deve estar em (...) em zsh (mas zsh tem um operador dedicado para correspondência de intervalo de número) e @(...) em ksh (ou bash com extglob on).

Então, com zsh :

cp -r ~/copyDest/(*[^0-9]|)<20-32>(|[^0-9]*) ~/pasteDest

Sem o (*[^0-9]|) , também corresponderia a foo120

Com ksh ou bash -O extglob (ou use shopt -s extglob dentro de bash ) ou zsh -o kshglob ( set -o kshglob dentro de zsh ), o equivalente (exceto na ordem em que os arquivos são copiados) ficaria assim:

(
  LC_ALL=C
  cp -r ~/copyDest/?(*[^0-9])*(0)@(2[0-9]|3[0-2])?([^0-9]*) ~/pasteDest
)

Com ksh ou bash, na maioria dos sistemas e na maioria das localidades diferentes de C, [0-9] combina muito mais caracteres que 0123456789, portanto, o LC_ALL=C (que também afeta a ordem de classificação da expansão glob). Se os seus nomes de arquivo contiverem apenas caracteres ASCII, você poderá omiti-lo, pois não acredito que nenhum código de idioma em qualquer sistema sã teria caracteres ASCII diferentes de 0123456789 correspondido por [0-9] . Outra alternativa é substituir [0-9] por [0123456789] .

Observe também que, exceto em zsh -o kshglob , se o padrão não corresponder a nenhum arquivo, cp será chamado com um argumento literal .../?(*[^0-9])*(0)@(2[0-9]|3[0-2])?([^0-9]*) (um nome de arquivo válido, porém improvável) que, se existir, será copiado (ou cp retornaria um erro de outra forma). Em bash , você pode usar a opção failglob para obter um comportamento mais próximo do mais básico de zsh (de cancelar o comando se o padrão não corresponder).

Acima, tomamos um cuidado especial ao copiar arquivos chamados foo20.txt , foo00020.txt , mas não foo120.txt ou foo200.txt (mesmo que o nome deles contenha 20). Ainda copia foo32.12.txt ou foo-1E-20.txt ou foo0x20.txt arquivos.

Se você ainda quiser copiar arquivos foo120 ou foo200 , isso se tornará muito mais simples:

  • zsh :

    cp -r ~/copyDest/*<20-32>* ~/pasteDest
    
  • bash -O extglob e co:

    cp -r ~/copyDest/*@(2[0123456789]|3[012])* ~/pasteDest
    
por 24.10.2018 / 12:30
7

Você não leu o manual sobre correspondência de padrões de shell e assumiu que é o mesmo que é comumente chamado de "expressões regulares". Apenas o fato de que o operador * , que você usa em seu exemplo, tem um significado diferente, deve ser uma sugestão de que eles não são os mesmos.

Com o bash (e alguns outros shells) você pode usar o operador {,} para o efeito desejado:

cp -r ~/copyDest/*{2[0-9],3[0-2]}* ~/pasteDest

Mas cuidado, existem diferenças. Isso é o mesmo que escrever

cp -r ~/copyDest/*2[0-9]* ~/copyDest/*3[0-2]* ~/pasteDest

Isso significa que, se um dos padrões não corresponder a nenhum arquivo, ele será passado como um argumento para cp e cp reclamará que o arquivo não existe. Você pode definir a opção nullglob shell para evitar isso.

    
por 24.10.2018 / 10:46
7

bash abordagem. Como um bônus, ele imprime os números para os quais um arquivo correspondente não foi encontrado.

[steve@instance-2 ~]$ find copyDest pasteDest
copyDest
copyDest/file15
copyDest/file20
copyDest/file25
copyDest/file32
copyDest/file33
pasteDest
[steve@instance-2 ~]$ cp -pr ~/copyDest/*{20..32}* pasteDest
cp: cannot stat ‘/home/steve/copyDest/*21*’: No such file or directory
cp: cannot stat ‘/home/steve/copyDest/*22*’: No such file or directory
cp: cannot stat ‘/home/steve/copyDest/*23*’: No such file or directory
cp: cannot stat ‘/home/steve/copyDest/*24*’: No such file or directory
cp: cannot stat ‘/home/steve/copyDest/*26*’: No such file or directory
cp: cannot stat ‘/home/steve/copyDest/*27*’: No such file or directory
cp: cannot stat ‘/home/steve/copyDest/*28*’: No such file or directory
cp: cannot stat ‘/home/steve/copyDest/*29*’: No such file or directory
cp: cannot stat ‘/home/steve/copyDest/*30*’: No such file or directory
cp: cannot stat ‘/home/steve/copyDest/*31*’: No such file or directory
[steve@instance-2 ~]$ find copyDest pasteDest
copyDest
copyDest/file15
copyDest/file20
copyDest/file25
copyDest/file32
copyDest/file33
pasteDest
pasteDest/file20
pasteDest/file25
pasteDest/file32
[steve@instance-2 ~]$
    
por 24.10.2018 / 12:03
3

Quando preciso lidar com arquivos numerados, costumo usar um loop for e seq :

for i in $(seq 20 32); do cp -r ~/copyDest/*${i}* ~/pasteDest; done
    
por 24.10.2018 / 13:53
1

Você precisa fazer correspondência de padrão, NÃO correspondência de regex. Olhe para a página de manual do seu shell. Tente algo como

ls  *2[0-9]* *3[0-2]*

i.e. implementar a alternação, fornecendo dois padrões.

    
por 24.10.2018 / 10:50