toque em todas as pastas em um diretório

13

Estou tentando atualizar os carimbos de data e hora de todas as pastas no cwd usando este:

for file in `ls`; do touch $file; done

Mas isso não parece funcionar. Alguma idéia do porquê?

javamonkey79
fonte

Respostas:

21

Todas as respostas até agora (assim como o seu exemplo na pergunta) pressupõem que você queira touchtudo no diretório, mesmo que tenha dito "toque em todas as pastas". Se o diretório contiver arquivos e pastas e você desejar apenas atualizar as pastas, poderá usar find:

$ find . -maxdepth 1 -mindepth 1 -type d -exec touch {} +

Ou se sua findimplementação não suportar os predicados -mindepth/ não padronizados -maxdepth:

$ find . ! -name . -prune -type d -exec touch {} +

Este:

$ touch -c -- */

Deve funcionar na maioria das conchas, exceto que:

  • ele também fará touch links simbólicos para diretórios , além de diretórios simples
  • omitirá os ocultos
  • se não há nenhum diretório ou link simbólico para o diretório, seria criar um arquivo chamado *em outras do que conchas csh, tcsh, zsh, fishou o shell Thompson (que iria relatar um erro em vez disso). Aqui, estamos usando -cpara contornar isso, embora ainda possa ser touchchamado um arquivo que não seja de diretório *.

Com zsh, touchapenas para diretórios, incluindo os ocultos:

touch -- *(D/)
Michael Mrozek
fonte
O que é o '{} \ +'?
precisa saber é o seguinte
3
A sintaxe {} \+é especial find- leia a página de manual para obter mais informações. Eu acho touch -c ./*/que também funcionaria.
jw013
2
Você deve incluir -maxdepth 1no comando, para que findnão seja recursivo em subpastas. O OP parece querer tocar apenas nas pastas no cwd, não nas subpastas.
Steven segunda-feira
1
@ jw013 Seria - você manter anexando boas idéias para respostas de outras pessoas :)
Michael Mrozek
Por que você escaparia do caractere +? Existem conchas que interpretam isso?
Witiko 30/08/16
11

Experimentar

touch ./*

Evita o forloop desnecessário que geraria um novo processo para cada arquivo e funciona para todos os nomes de arquivos, mesmo aqueles com espaços ou com opções parecidas (como -t). O único momento em que isso não funcionaria é se você não tiver arquivos (sem pontos) no diretório e, nesse caso, acabaria criando um arquivo chamado *. Para evitar isso, no caso específico da touchmaioria das implementações, há uma -copção (também chamada --no-createnas versões GNU) de não criar arquivos inexistentes, ou seja,

touch -c ./*

Veja também as boas referências em resposta de jasonwryan assim como este um .

jw013
fonte
1
O que acontecerá se você tiver 1 milhão de pastas no cwd?
Steven segunda-feira
Se você se deparar com problemas do tipo "lista de argumentos muito longa", provavelmente é melhor mudar para ferramentas "mais pesadas", como find . -type d -maxdepth1 -print0 | xargs -0 toucha resposta de MichaelMrozek acima.
jw013
7

Você não deve tentar analisar a saída dels .

Além disso, você deve citar seu "$file"para capturar qualquer espaço em branco. Consulte http://www.grymoire.com/Unix/Quote.html

Algo assim pode alcançar o que você procura:

for file in *; do touch "$file"; done

Veja as duas primeiras Bash Pitfalls para uma explicação mais completa.

jasonwryan
fonte
2
Perto, mas não exatamente. A touch ./*deve funcionar na maioria dos casos. Realmente não há necessidade do forloop, pois touchpode levar vários arquivos, e você precisa ./lidar com arquivos com nomes como --helpcorretamente. Este é um bom recurso sobre o assunto.
jw013
Por que '*' funciona?
Javaonkey79
@ javamonkey79 É uma casca brilhante .
jw013
1
@ jw013 Excelente ponto: e obrigado pelo link do veículo com rodas.
jasonwryan
Observe que *não captura arquivos e diretórios cujo nome começa com um ponto. Uma maneira de corrigir isso é ativar a dotglobopção de shell via shopt -s dotglob.
Witiko 30/08/16
-1
for file in `find .`; do touch $file; done
mikematic
fonte