Estou tentando criar um diretório que abrigue todos e apenas meus PDFs compilados a partir do LaTeX. Eu gosto de manter cada projeto em uma pasta separada, todos alojados em uma grande pasta chamada LaTeX
. Então eu tentei correr:
rsync -avn *.pdf ~/LaTeX/ ~/Output/
que deve encontrar todos os PDFs ~/LaTeX/
e transferi-los para a pasta de saída. Isso não funciona. Diz-me que não foi encontrado nenhum resultado para " *.pdf
". Se eu deixar de fora esse filtro, o comando listará todos os arquivos em todas as pastas do projeto no LaTeX. Portanto, há um problema com o filtro * .pdf. Tentei substituir ~/
pelo caminho completo para o meu diretório pessoal, mas isso não teve efeito.
Estou usando o zsh. Tentei fazer o mesmo no bash e até com o filtro que listava todos os arquivos em todos os subdiretórios ... O que está acontecendo aqui?
Por que o rsync não está entendendo meu filtro apenas de pdf?
ESTÁ BEM. Então atualize: Não, estou tentando
rsync -avn --include="*/" --include="*.pdf" LaTeX/ Output/
E isso me dá toda a lista de arquivos. Eu acho que porque tudo corresponde ao primeiro padrão ...
**
padrão zsh ) deve funcionar.Respostas:
TL, DR:
Rsync copia a (s) fonte (s) para o destino. Se você passar
*.pdf
como fontes, o shell o expande para a lista de arquivos com a.pdf
extensão no diretório atual. Nenhuma passagem recursiva acontece porque você não passou nenhum diretório como fonte.Então você precisa executar
rsync -a ~/LaTeX/ ~/Output/
, mas com um filtro para dizer ao rsync para copiar.pdf
apenas os arquivos. As regras de filtro do Rsync podem parecer assustadoras quando você lê o manual, mas você pode criar muitos exemplos com apenas algumas regras simples.Inclusões e exclusões:
--exclude=*~
,--exclude=/some/relative/location
(em relação ao argumento origem, por exemplo, este exclui~/LaTeX/some/relative/location
).--include=*/
) e exclua o restante com--exclude='*'
. Isto é porque:--include='directory/***'
fará isso.Padrões:
/
, será aplicado ao diretório sans do nome do arquivo./
, ele se aplicará apenas aos diretórios./
, ele se aplica a todo o caminho do diretório que foi passado como argumento pararsync
.*
qualquer substring de um único componente de diretório (ou seja, nunca corresponde/
);**
corresponde a qualquer substring de caminho.Se um argumento de origem terminar com a
/
, seu conteúdo será copiado (rsync -r a/ b
criadob/foo
para todosa/foo
). Caso contrário, o próprio diretório é copiado (rsync -r a b
criab/a
).Portanto, aqui precisamos incluir
*.pdf
, incluir diretórios que os contenham e excluir todo o resto.Observe que isso copia todos os diretórios, mesmo aqueles que não contêm arquivos ou subdiretórios correspondentes. Isso pode ser evitado com a
--prune-empty-dirs
opção (não é uma solução universal, pois você não pode copiar um diretório nem mesmo combiná-lo explicitamente, mas esse é um requisito raro).fonte
**
padrão do zsh ), isso recria a estrutura de diretórios no diretório de destino. Eu não tenho certeza se é isso que o OP quer .../etc/lsyncd/lsyncd.conf.lua
arquivo. Tem alguma ideia?O padrão é incluir tudo, portanto, você deve excluir explicitamente tudo depois de incluir os arquivos que deseja transferir. Remova o --dry-run para realmente transferir os arquivos.
Se você começar com:
A correspondência gananciosa excluirá tudo imediatamente.
Se você tentar:
Somente os arquivos pdf na pasta de nível superior serão transferidos. Ele não seguirá nenhum diretório, pois esses são excluídos por '*'.
fonte
--prune-empty-dirs
(ou atalho-m
), você ainda poupa muitos diretórios vazios no destino, exceto, é claro, que deseja que eles sejam um lembrete ou um plano estrutural./etc/lsyncd/lsyncd.conf.lua
arquivo. Tem alguma ideia?Se você usar um padrão como
*.pdf
, o shell "expande" esse padrão, ou seja, substitui o padrão por todas as correspondências no diretório atual. O comando que você está executando (neste caso, rsync) não tem conhecimento do fato de que você tentou usar um padrão.Quando você está usando o zsh , existe uma solução fácil: O
**
padrão pode ser usado para corresponder pastas recursivamente. Tente o seguinte:fonte
rsync -avn ~/LaTeX/**/*.pdf ~/Output
, mas a solução com--include
é mais escalável de qualquer maneira.**
podendo ser útil em outras situações também.cd ~/Latex && cp -p **/*.pdf ~/Output
a evitar um erro de "linha de comando muito longa".Você pode usar
find
e uma lista intermediária de arquivos (files_to_copy
) para resolver seu problema. Verifique se você está no diretório inicial e, em seguida:find LaTeX/ -type f -a -iname "*.pdf" > files_to_copy && rsync -avn --files-from=files_to_copy ~/ ~/Output/ && rm files_to_copy
Testado com Bash.
fonte
-exec
opção find ou usandoxargs
. Algo como:find LaTeX/ -type f -iname "*.pdf" -print0 | xargs -0 -i rsync -avn {} Output/
standalone
ou que não possui um.tex
arquivo com o mesmo nome, pois essas serão imagens incluídas em algum documento ...--files-from
aceita a leitura de stdin. Isso funcionaria #find LaTeX/ -type f -a -iname "*.pdf" | rsync -avn --files-from=- ~/ ~/Output/
A julgar pela seção "INCLUIR / EXCLUIR REGRAS DE PADRÃO" da página de manual , a maneira de fazer isso é
A diferença crítica entre esta e a resposta do kbrd é a
--include="*/"
flag, que diz ao rsync para seguir em frente e copiar os diretórios que encontrar, independentemente do nome. Isso é necessário porque o rsync não recursará em um subdiretório, a menos que tenha sido instruído a copiar esse subdiretório.Além disso, observe que as aspas impedem que o shell tente expandir os padrões para nomes de arquivos em relação ao diretório atual e siga um destes procedimentos:
Como obter êxito e atrapalhar o seu filtro (não é muito provável no meio de uma bandeira como essa, embora você nunca saiba quando alguém criará um arquivo chamado
--include=foo.pdf
...)Falha e potencialmente produzindo um erro em vez de executar o comando (como você descobriu o zsh por padrão).
fonte
include
coisas extras já existentes lá não mudam nada. Se você ver o que quero dizer ...--exclude="*"
depois do--include="*.pdf"
, ou isso irá transferir tudo.Que tal agora:
fonte
man rsync
coloca o filtro após as opções e antes da origem / destino. Eu tentei isso e não funcionoua
opção é para arquivar e, entre outras coisas, torna a cópia recursiva.Aqui está algo que deve funcionar sem usar o find. A diferença das respostas já postadas é a ordem das regras de filtro. As regras de filtro em um comando rsync funcionam muito como as regras do iptable, a primeira regra que um arquivo corresponde é a usada. Na página do manual :
Portanto, você precisa de um comando da seguinte maneira:
Observe o padrão "**. Pdf". De acordo com a página do manual :
No meu pequeno teste, isso funciona recursivamente na árvore de diretórios e seleciona apenas os pdfs.
fonte
*.pdf
no diretório de nível superior (mas não~/LaTeX/foo/bar.pdf
).**
. Seria bom ter um exemplo disso. ;)Esta é a minha solução preferida:
O
find
comando é mais fácil de entender do que as regras de inclusão / exclusão dersync
:-)Se você deseja copiar apenas arquivos pdf, altere
.jpg
para.pdf
fonte