Eu tenho uma lista de arquivos separados por espaços em um arquivo list.txt
. Eu gostaria de copiá-los para uma nova pasta.
Eu tentei fazer:
cp `cat list.txt` new_folder
mas não funcionou.
Como você faria isso ?
Atualizar:
Obrigado por todas as suas respostas muito interessantes. Eu não pedi muito :)
Depois de ter tentado a solução acima uma segunda vez, parece que cp
a ajuda de uso foi impressa porque a pasta new_folder
ainda não existia! Desculpe, parece ser um erro estúpido ... Quando eu crio a pasta antes, ela funciona.
No entanto, aprendi muito com todas as suas respostas e soluções, obrigado pelo tempo que você leva para escrevê-las.
Respostas:
Tente usar xargs:
Atualizar:
Eu fiz isso no OS X, que tem uma versão diferente das versões GNU / Linux. O
xargs
que vem do GNU findutils não tem,-J
mas tem o-I
que é semelhante (como Dennis Williamson apontou em um comentário). A versão do xargs para OS X tem ambos-I
e-J
que têm comportamentos ligeiramente diferentes - ambos funcionarão para esta pergunta original.fonte
xargs
não tem-J
o-I
que parece fazer a mesma coisa. Qual versãoxargs
e qual OS / distribuição você possui?xargs --version
retorna uma mensagem de erro de uso. Provavelmente é uma versão BSD do xargs. O uso de-I
e-J
são sutilmente diferentes. Atualizarei minha resposta com exemplos bem formatados.-J
e-I
:)Não é necessário
cat
:Ou usando opções longas:
Aqui estão algumas versões do shell. Observe que algumas variáveis não estão entre aspas ou os
for
loops são usados especificamente porque o OP especificou que os nomes de arquivos são delimitados por espaço. Algumas dessas técnicas não funcionam para entrada de nome de arquivo por linha, na qual os nomes de arquivos contêm espaços em branco.Bater:
ou
sh (ou Bash):
ou
ou
ou
fonte
-t
necessárioxargs -a list.txt cp -t new_folder
?-t
é uma opção decp
. Ele copia todos os argumentos de origem no diretório de destino especificado. Aqui, ele permite que o destino seja especificado antes da fonte que é adicionada peloxargs
comando.Tive uma resposta embaraçosamente abrangente aqui antes, mas a resposta de Denis me lembrou que eu sentia falta da coisa mais básica. Então, eu apaguei minha resposta original. Mas como ninguém disse essa coisa muito básica, acho que vale a pena colocar aqui.
A pergunta original é "Eu tenho um arquivo de texto com uma lista de nomes de arquivos separados por espaço. Como posso copiá-los para um diretório de destino". No começo, isso pode parecer complicado ou complicado, porque você acha que precisa extrair os itens do arquivo de uma maneira específica. No entanto, quando o shell processa uma linha de comando, a primeira coisa que faz é separar a lista de argumentos em tokens e (aqui está o que ninguém disse de maneira definitiva) os espaços separados por tokens . (As novas linhas também separam os tokens, e é por isso que o teste de Doug Harris com uma lista separada de novas linhas teve o mesmo resultado.) Ou seja, o shell espera e já pode lidar com uma lista separada por espaço.
Portanto, tudo o que você precisa fazer aqui é colocar a lista separada por espaço (que você já possui) no lugar certo em seu comando. Seu comando é uma variação disso:
O único problema é que você deseja obter a lista de arquivos de 1 a # do seu arquivo de texto.
Como Dennis aponta em seu comentário, sua tentativa original (
cp
cat list.txtnew_folder
) já deveria ter funcionado. Por quê? Como o comando internocat list.txt
é processado primeiro pelo shell e se expandefile1 file2 file3...file#
, o que é exatamente o que o shell espera e deseja nessa parte do comando. Se não funcionou, então (1) você teve um erro de digitação ou (2) seus nomes de arquivos eram de alguma forma estranhos (eles tinham espaços ou outros caracteres incomuns).A razão pela qual todas as respostas de Dennis funcionam é simplesmente que elas fornecem a lista necessária de arquivos para
cp
trabalhar, colocando essa lista onde ela pertence em todo o comando. Novamente, o próprio comando é este na estrutura:É fácil ver como tudo isso se reúne nesta versão:
$()
faz com que o shell execute o comando entre parênteses e substitua sua saída nesse ponto da linha maior. Em seguida, o shell executa a linha como um todo. A propósito,$()
é uma versão mais moderna do que você já estava fazendo com backticks (`). Próximo:<
é um operador de redirecionamento de arquivo. Diz ao shell para despejar o conteúdo dalist.txt
entrada padrão. Como o$()
bit é processado primeiro, eis o que acontece em etapas:cp $(<list.txt) new_folder
# split line into three tokens: cp, $(<list.txt), new_folder
cp file1 file2 file3...file# new_folder
# substitute result of $(<list.txt) into the larger command
Obviamente, o passo 2 é simplesmente o
cp
comando normal que você queria.Percebo que estou batendo muito nesse cavalo (talvez muito morto), mas acho que vale a pena. Entender exatamente como o shell processa um comando pode ajudá-lo a escrevê-lo melhor e simplificar muito. Também mostrará onde é provável que os problemas estejam escondidos. Nesse caso, por exemplo, minha primeira pergunta para você deveria ter sido sobre nomes de arquivos engraçados ou um possível erro de digitação. Não foram necessárias acrobacias.
fonte
--parents
sinalizador. Você pode torná-lo detalhado-v
para um registro do que foi copiado. Se você deseja manter as permissões, precisa do sinalizador-a
ou-p
. Ou sejacp --parents -av $(<list.txt) new_folder
,. Isso tudo pressupõe que sua lista de arquivos seja realmente todos os arquivos; caso contrário, você também pode precisar do-r
sinalizador para receber novamente.--parents
bandeira não existe lá. Sua versão (derivada do BSD)cp
fornece apenas opções curtas, não opções longas no estilo GNU. Para um estilo BSDcp
, o sinalizador para cópia recursiva é maiúsculo-R
, não minúsculo.