Eu sou capaz de localizar arquivos em uma pasta que contém uma sequência de texto específica usando este comando:
grep -lir 'string' ~/directory/*
Como movo os arquivos que aparecem no resultado acima para outro local?
Eu sou capaz de localizar arquivos em uma pasta que contém uma sequência de texto específica usando este comando:
grep -lir 'string' ~/directory/*
Como movo os arquivos que aparecem no resultado acima para outro local?
Respostas:
Como sempre, cuidado com grep -r
. -r
não é uma opção padrão e, em algumas implementações, como todas as versões muito recentes do GNU grep
, segue links simbólicos ao descer a árvore de diretórios, o que geralmente não é o que você deseja e pode ter implicações graves se, por exemplo, houver um link simbólico para "/ "em algum lugar na árvore de diretórios.
Na filosofia do Unix, você usa um comando para procurar arquivos em diretórios e outro para examinar seu conteúdo.
Usando ferramentas GNU, eu faria:
xargs -r0 --arg-file <(find . -type f -exec grep -lZi string {} +
) mv -i --target-directory /dest/dir
Mas, mesmo assim, tenha cuidado com as condições de corrida e possíveis problemas de segurança se você o executar como um usuário em um diretório gravável por outro usuário.
xargs
encerrado antes da leitura até o final de seu arquivo arg, o que não deveria acontecer, a menos que o xargs se matasse ou falhasse por qualquer motivo, nesse caso, espero que você também veja um erro sobre isso.
Use xargs
em conjunto com mv
a terceira sintaxe:mv [OPTION]... -t DIRECTORY SOURCE...
grep -lir 'string' ~/directory/* | xargs mv -t DEST
Cuidado com arquivos que contêm caracteres especiais (espaços, aspas). Se esse for o seu caso, filtrar a lista com sed
(adicionar aspas aos nomes de arquivos com s/^/'/;s/$/'/
) pode ajudar, mas você precisa ter certeza de que essas aspas não aparecerão nos nomes dos arquivos. O GNU grep
tem a opção -Z
/ --null
para encerrar nomes de arquivos NUL.
Uma alternativa para a terceira sintaxe para mv
é usar xargs
com a sequência de marcações ( -I
).
Outra opção é a substituição de comandos - $( )
ou backticks ``
(no bash), como mencionado na resposta de ire_and_curses.
Se os nomes dos arquivos não contiverem caracteres especiais (espaço em branco ou \[*?
), use a substituição de comando :
mv `grep -lir 'string' ~/directory/*` destination/
Usando apenas os recursos especificados no POSIX e não fazendo suposições sobre os nomes de arquivos:
find ~/directory -type f -exec grep -qiF 'string' {} \; -exec mv {} /path/to/dest \;
Notas:
Você disse "string" e não "pattern", portanto a opção -F
(pesquisa de string fixa) grep
parece apropriada.
Se o diretório de destino estiver em qualquer lugar dentro do diretório de pesquisa, você poderá ter algumas condições desagradáveis de corrida.
Usando o GNU paralelo :
grep -i -Z -r -l 'string' . | parallel 'mv {} destination/{}'
ht / @ lin-dong por sua resposta original com xargs.
Suponha que você tenha o diretório de destino como 'externo' e precise mover todos os arquivos XLS, tente o comando abaixo
sudo mv find /var/log/ -type f -name "*.xls"
/ externo /
grep -i -Z -r -l 'string' . | xargs -I{} mv {} ./folder_name