Como você usa expressões regulares com o comando cp no Linux?

22

Estou tentando copiar apenas um subconjunto de arquivos de um diretório para outro usando, cpno entanto, sou recebido com a mensagem cp: cannot stat [^\.php]': No such file or directory. Existe uma maneira de usar expressões regulares apenas usando o cpcomando?

AmendoimMacaco
fonte

Respostas:

29

Não.

O cpcomando não possui a capacidade de processar nenhum de seus argumentos como expressões regulares. Até curingas não são manipulados por ele (ou pela maioria dos executáveis); ao contrário, eles são manipulados pela concha.

cp test/* test2/é realmente expandido pelo bash, e tudo o que cprealmente vê para seus argumentos é cp test/file1 test/file2 test/file3 test2/(ou o que for apropriado com base no conteúdo real de test/).

Além disso, não acho que sua expressão [^\.php]corresponda ao que você deseja (não corresponde apenas aos arquivos que contêm .php).

Você provavelmente deseja examinar o findutilitário para filtrar uma lista de arquivos com base na expressão regular e, em seguida, usar xargspara aplicar a lista de arquivos retornados ao cpcomando (presumindo que find não tenha um manipulador interno para copiar arquivos; eu ' não estou intimamente familiarizado com a ferramenta).

Você pode tentar:

find . ! -iregex ".*\.php.*" -exec cp {} /destination/folder/ \;

Isso diz para procurar no diretório atual recursivamente os arquivos que não contêm ".php" no caminho e copiá-los para /destination/folder/.

Conforme solicitado, uma análise mais específica dos argumentos:

  • . - Local para iniciar a pesquisa - nesse caso, o diretório atual
  • ! - Operador "Não", inverta o resultado do próximo teste
  • -iregex- Teste de expressão regular sem distinção entre maiúsculas e minúsculas. O próximo argumento é a expressão.
  • ".*\.php.*"- Correspondência de expressão regular <Anything>.php<Anything>- Qualquer arquivo que tenha ".php" em algum lugar do caminho. (Observe que, além de estar dentro de uma pasta que contenha ".php" no nome, você precisará de uma expressão mais complexa para corresponder apenas aos arquivos)
  • -exec- Execute um comando se os testes anteriores retornarem true. O próximo argumento é o comando, todos os argumentos restantes até ;são passados ​​para o comando. o {}é um argumento especial que representa o nome do arquivo.
  • cp - O comando que find` deve ser executado em cada um dos nomes de caminhos correspondentes.
  • {}- O caminho para o arquivo que foi encontrado, passado cpcomo argumento para que ele saiba qual arquivo copiar
  • /destination/folder/- argumento passado para cp, dizendo para cponde deveria copiar o arquivo.
  • \;- Este é o ;terminador que você -execestá procurando. Nós o escapamos com um \para que seu shell não tente analisá-lo e, em vez disso, o alimenta como um argumento para o comando ( find)

É bastante difícil de escrever uma expressão regular que corresponde a "cordas que não têm .php", de modo que em vez dizer findpara procurar strings que não contêm .phpe depois invertido os resultados com !.

Darth Android
fonte
2
find . -name [^\.php] -exec cp {} /path/to/location \;tenha cuidado com arquivos com caracteres especiais.
25412 Rob
@Darth Android - Obrigado. Eu não estava ciente disso cpe outros binários não foram capazes de expandir expressões regulares. Você se importaria de elaborar o que cada uma das opções e argumentos significa no exemplo de exemplo que você deu? Eu sei que .se refere ao diretório atual, mas o que !, {}, \;, etc referem-se bem o que eles significam? Por exemplo, por que você tem que escapar do ;?
PeanutsMonkey
@Rob - O que você quer dizer com arquivos especiais?
PeanutsMonkey
@Rob - Tentei uma expressão semelhante para remover arquivos específicos, mas acabou excluindo todos os arquivos no diretório. Meu comando foi, find . -name '[^\.txt]' -exec rm {} \;portanto, minha relutância em usar find. Provavelmente foi um erro da minha parte, mas não tenho certeza do que fiz de errado. Tanto quanto o meu entendimento {}se refere a cada arquivo encontrado pelo comandofind . -name '[^\.txt]'
PeanutsMonkey
O que você está tentando combinar com a regex?
26412 Rob
10

Você pode usar algumas outras ferramentas do console, como grep e xargs.

ls -1 some_folder | egrep 'some_extended_regex' | xargs cp -t destination_folder
0xAF
fonte
Qual é a {}diferença de -t?
PeanutsMonkey
2
Não há muito neste caso. A sintaxe alternativa para xargs seria 'xargs cp {} destination_folder'. A sintaxe cp padrão utiliza uma ou várias fontes e um destino no final. Quando você usa a opção -t, pode especificar o destino após a opção -t e usar o restante da linha para fontes. Eu apenas acho a opção -t mais conveniente nesse caso. No outro exemplo, o {} é substituído pelo que é canalizado para xargs (stdin), neste caso, o nome do arquivo.
0xAF
-1

Você pode executar o seguinte comando fácil de usar:

find /home/usr/search_dir -iname *file_name_portion*.txt | xargs cp -t /home/usr/destination_folder

haa legal !!

Nisan Chhetri
fonte