De acordo com as Leis 12.965/2014 e 13.709/2018, que regulam o uso da Internet e o tratamento de dados pessoais no Brasil, ao me inscrever na newsletter do portal DICAS-L, autorizo o envio de notificações por e-mail ou outros meios e declaro estar ciente e concordar com seus Termos de Uso e Política de Privacidade.
Colaboração: Paulo Roberto Bagatini
Data de Publicação: 30 de março de 2015
Ao longo dos anos fui amontoando alguns arquivos .reg com configuração personalizada do PuTTY. Não é muita coisa, mas está tudo espalhado em um HD USB com mais de 1 TiB de dados e não há a menor chance de lembrar quantos são, em que diretórios estão e como se chamam; só sei que provavelmente têm "putty" no nome, alguma alternância entre maiúsculo e minúsculo, e a extensão é "reg".
Como achá-los e copiá-los automaticamente para um único diretório, cuidando para não sobrescrever os que tiverem o mesmo nome? Bom, se cada arquivo for copiado com seu caminho original para dentro do novo diretório "pai", certamente não haverá nenhuma sobreposição.
A primeira técnica será a forma rápida, limpa e suficientemente nerd de fazer isso (no Unix, MacOSX e Windows com CygWin): com um singelo cp associado a um find.
Primeiro preparamos adequadamente o ambiente:
$ padrao="*putty*.reg" $ pesquisa="/longa/raiz/comum/a/todos/os/arquivos/e/que/nao/interessa/manter/" $ destino="/diretorio/para/os/arquivos/encontrados/" $ mkdir -p "$destino" $ alias time="/usr/bin/time -f %E"
Então executamos o comando:
$ ( cd "$pesquisa"; cp -va --parents $(time find . -type f -iname "$padrao") "$destino" )
O alias do comando time é apenas um plus a mais :-p para saber em um formato user friendly quanto tempo a pesquisa do find demorou.
Beleza, funcionou! Em 17 min varreu 1.3 TiB e copiou 28 arquivos.
Mas como nem tudo são flores no mundo encantado da TI, esse método tem pelo menos dois pontos de falha em potencial.
Um deles é o tamanho da entrada gerada pela saída do find. No meu Linux 3.16.0 em arquitetura 32 bits, se todos os argumentos do cp resultarem em uma string com mais de 2.097.152 (=2^21, bc -l <<< "scale=5;l(2097152)/l(2)"
;-) caracteres, ele vai reclamar:
$ ( cd "$pesquisa"; find . -type f -iname "$padrao" | wc -c ) # mostra com quantos bytes fica a lista de argumentos resultante do padrão 2981219 $ ( cd "$pesquisa"; cp -va --parents $(find . -type f -iname "$padrao") "$destino" ) bash: /bin/cp: Lista de argumentos muito longa $ # ou, em inglês: $ ( cd "$pesquisa"; LANGUAGE=C cp -va --parents $(find . -type f -iname "$padrao") "$destino" ) bash: /bin/cp: Argument list too long
Podemos até não gostar dessa limitação de 2 MiB, mas lembremos que o "comprimento" dos comandos no terminal do Windows não passa de míseros (8Ki-1)B >:-) (support.microsoft.com/pt-br/kb/830473)
O tamanho que a lista de argumentos pode ter no Unix está definido na constante ARG_MAX e, pelo menos no Linux, pode ser consultado com o comando getconf:
$ getconf ARG_MAX 2097152 $ getconf -a # todos as constantes $ getconf -a | grep MAX # constantes explicitamente relacionadas a limites máximos, vale a pena uma olhada
Alguma informação sobre o ARG_MAX está disponível em in-ulm.de/~mascheck/various/argmax/, inclusive uma tabela comparando seu valor em vários sistemas operacionais.
Ainda que o processo sobreviva ao risco do tamanho final da lista de parâmetros do cp, pode não escapar da existência de diretórios ou arquivos com espaço no nome (/longa/raiz/
comum a
/todos/os/arquivos/e/que/nao/interessa/manter/configs/
putty fileserver.reg
):
cp: impossível obter estado de /longa/raiz/comum : Arquivo ou diretório não encontrado cp: impossível obter estado de a/todos/os/arquivos/e/que/nao/interessa/manter/configs/putty : Arquivo ou diretório não encontrado cp: impossível obter estado de fileserver.reg : Arquivo ou diretório não encontrado
Para contornar esse outro ponto de falha, precisamos de alguma técnica que permita deixar entre aspas o nome com caminho de cada arquivo, ou o que quer que o represente.
Ignorando a alternativa óbvia de iterar a saída do find em um loop, uma segunda técnica permite driblar simultaneamente o problema do tamanho da lista de argumentos e dos espaços em nomes, de pelo menos duas formas:
$ ( cd "$pesquisa"; time find . -type f -iname "$padrao" -exec cp -va --parents "{}" "$destino" \; ) $ ( cd "$pesquisa"; time find . -type f -iname "$padrao" | xargs -I+ cp -va --parents "+" "$destino" )
Por fim, uma terceira técnica combina o comando find com duas chamadas do comando tar. Tem características interessantes:
Usando ssh, é especialmente importante verificar se temos as permissões necessárias para criar o diretório $destino.
O tar pode ser usado com xargs para contornar o estouro do tamanho da lista de argumentos ou pode usar um arquivo com a lista de entrada a ser manipulada. Para evitar a criação explícita de um arquivo intermediário, podemos aplicar substituição de processos (apoie.org/JulioNeves/PapoXI.htm#Substitui_o_de_processos, wikipedia.org/wiki/Process_substitution).
$ ( cd "$pesquisa"; time find . -type f -iname "$padrao" -print0 | xargs -0 tar cf - ) | tar xvf - -C "$destino" $ ( cd "$pesquisa"; tar cf - -T <(time find . -type f -iname "$padrao") ) | tar xvf - -C "$destino" $ chave="/arquivo/com/chave/privada/sem/passphrase" $ remoto="user@host" $ # compactação gzip $ ( cd "$pesquisa"; tar cf - -T <(time find . -type f -iname "$padrao") ) | ssh -CTi "$chave" $remoto "mkdir -p '$destino'; tar xvf - -C '$destino'" $ # compactação bzip2 $ ( cd "$pesquisa"; tar jcf - -T <(time find . -type f -iname "$padrao") ) | ssh -Ti "$chave" $remoto "mkdir -p '$destino'; tar jxvf - -C '$destino'" $ # compactação lzma $ ( cd "$pesquisa"; tar cf - -T <(time find . -type f -iname "$padrao") ) | xz -9e | ssh -Ti "$chave" $remoto "mkdir -p '$destino'; xz -d | tar xvf - -C '$destino'"
This policy contains information about your privacy. By posting, you are declaring that you understand this policy:
This policy is subject to change at any time and without notice.
These terms and conditions contain rules about posting comments. By submitting a comment, you are declaring that you agree with these rules:
Failure to comply with these rules may result in being banned from submitting further comments.
These terms and conditions are subject to change at any time and without notice.
Comentários