Eu tenho uma pasta com muitos arquivos. Quero copiar todos os arquivos que começam com estes nomes (separados por espaço):
abc abd aer ab-x ate
para outra pasta. Como eu posso fazer isso?
Responder1
Com csh
, tcsh
, ksh93
, bash
, fish
ou zsh -o cshnullglob
, você pode usarexpansão de cintaeglobulandopara fazer isso ( --
não é necessário para esses nomes de arquivos, mas presumo que sejam apenas exemplos):
cp -- {abc,abd,aer,ab-x,ate}* dest/
Se preferir não usar a expansão de chaves, você pode usar um loop for (aqui sintaxe estilo POSIX/Bourne):
for include in abc abd aer ab-x ate; do
cp -- "$include"* dest/
done
Se você tiver uma quantidade muito grande de arquivos, isso poderá ser lento devido à invocação de cp
uma vez por inclusão. Outra maneira de fazer isso seria preencher um array e partir daí (aqui ksh93
ou sintaxe zsh
recente bash
):
files=()
includes=(abc abd aer ab-x ate)
for include in "${includes[@]}"; do
files+=( "$include"* )
done
cp -- "${files[@]}" dest/
Responder2
Uma nota sobre expansão de chaves versus globbing.
A expansão de chaves não é global (embora a distinção não seja tão clara em csh/tcsh onde ela se originou como em outros shells). É realizadoantesglobulando.
Então, quando você fizer isso:
cp {a,b}* /dest
É primeiro expandido para:
cp a* b* /dest
Isso significa que o shell terá que expandir dois globs, ou seja, obter a lista completa de arquivos duas vezes e ver quais correspondem ao padrão duas vezes.
Com zsh
, isso também significa que se algum glob não corresponder a nenhum arquivo, todo o comando será cancelado (o que você pode contornar ativando a cshnullglob
opção de se comportar como em csh).
Isso também significa que se você tiver
cp {a,ab}* /dest
cp
copiará os ab*
arquivos duas vezes.
Isso é diferente de:
cp @(a|b)* /dest
de ksh
ou bash -O extglob
ou zsh -o kshglob
, ou
cp (a|b)* /dest
de zsh
. Aí, é sóumglob, então será mais eficiente e os arquivos serão incluídos apenas uma vez.
Com zsh
, se você tiver a lista de prefixos em uma matriz:
prefixes=(abc abd aer ab-x ate)
cp -- (${(j:|:)~prefixes})* /dest
(acima, os prefixos são tratados como globos). Isso é juntar os elementos dos arrays |
e considerar o resultado como um glob ( ~
).
Se a lista for grande, o que você poderá descobrir é que a execução cp
falha com um“lista de argumentos muito longa”erro. Nesse caso, você pode usar zsh
a versão integrada cp
carregando o zsh/files
módulo ( zmodload zsh/files
).
Responder3
Por exemplo, tenho estes arquivos no diretório atual:
1-s2.0-S0038092X0000058X-main.pdf ANNDHW.pdf HPcalculation2 1-s2.0-S0306261999000422-main.pdf ANNlee.pdf HPcalculation3 ANNCanada.pdf HPcalculation HPcalculation4
Quero mover todos os arquivos começando da HP para a pasta:
./NewFolder/
Eu posso fazer:
cp ./HP* ./NewFolder/
./HP*
direi ao Linux que estou interessado em todos os arquivos da HP. O inverso é quando estou interessado em mover todos os arquivos que terminam em.pdf
. Posso colocar*
na frente de.pdf
:cp ./*.pdf ./NewFolder/
Responder4
Simplesmente você pode fazer
cp abc* abd* aer* ab-x* ate* DestinationPath
Uma solução para o seu problema estendido pode ser
- coloque todos os nomes de arquivos em uma lista, por exemplo, list0.txt
Copie tudo com
cp `cat list0.txt` DestinationPath # Não precisa de espaços em branco nos nomes dos arquivos
ou melhor,
enquanto lê o arquivo -r; faça cp "$arquivo" dest/ ; concluído <list0.txt
Notas:
- "$file" porque assim você pode lidar com o nome com espaço em branco dentro como
One Package.deb
-r
protege você de sequências de fuga.-r A barra invertida não atua como um caractere de escape. A barra invertida é considerada parte da linha. Em particular, um par barra invertida-nova linha não pode ser usado como continuação de linha