Como tocar tudo em um diretório, incluindo oculto, como diretório up '..'?

0

Esta questão tem paralelos para questionar " toque em todas as pastas em um diretório ".

Como touch tudo em um diretório,

  • recursivamente
  • incluindo entradas ocultas, como "diretório para cima" .. e .
  • sem remover a referência dos links simbólicos touch -h e
  • use um arquivo de referência touch -r <file> como a origem do registro de data e hora

    dentro de um script de shell ?

por Pro Backup 10.12.2017 / 22:09

1 resposta

3

Se o seu comando touch suportar -h para nenhuma desreferência :

find . -depth -exec touch -h -r "$reference_file" {} +
touch -c -h -r "$reference_file" ..

(note que -h implica -c (para evitar a criação do arquivo se ele não existir com o NetBSD / FreeBSD, mas não com o GNU ou o busybox touch (embora com o GNU touch ele não crie arquivos e imprima uma mensagem de erro), adicionando -c aqui para maior portabilidade).

Ou com um único comando find que poderia reduzir o número de comandos touch sendo executados:

find .. . -depth \( ! -name .. -o -prune \) -exec touch -c -h -r "$reference_file" {} +

Isto é, adicione .. à lista de arquivos dados a find , mas diga find para podar (não desça a ele).

Para um diretório arbitrário (bem aquele cujo caminho não começa com - :

find "$dir/.." "$dir/" \( ! -name .. -o -prune \) \
  -exec touch -c -h -r "$reference_file" {} +

(aqui usando $dir/ em vez de $dir para o caso em que $dir se refere a um symlink para um diretório).

Com o BSD find , você pode usar

find -f "$dir/.." -f "$dir/" \( ! -name .. -o -prune \) \
  -exec touch -c -h -r "$reference_file" -- {} +

para evitar os problemas com $dir , começando com - .

Embora você também possa fazer isso:

(
 cd -P -- "$dir/" &&
   exec find .. . \( ! -name .. -o -prune \) \
     -exec touch -c -h -r "$reference_file" {} +
)

(assumindo que $reference_file não é um caminho relativo).

Note que se $reference_file é um link simbólico, com GNU touch e -h , o tempo de modificação do symlink será usado (aquele do alvo seria usado sem -h ) enquanto com o NetBSD ( onde -h vem de ) e FreeBSD touch , o horário de modificação do destino é usado com ou sem -h .

Se estiver usando zsh , você pode usar sua globalização recursiva

autoload zargs
zargs -- $dir/{.,..,**/*(NDoN)} -- touch -c -h -r $reference_file --

(o oN para não classificar a lista pode ser omitido, apenas para otimização).

O ksh93 acabou por adicionar suporte para a globalização recursiva do zsh em 2005, com a opção globstar .

(set -o globstar; FIGNORE=
 command -x touch -c -h -r "$reference_file" -- ~(N)"$dir"/**)

Observe, entretanto, que ksh incluirá todas as entradas . e .. aqui, então todos os diretórios serão tocados várias vezes.

O

bash eventualmente copiou o globstar do ksh93 em 2009, mas foi inicialmente / quebrado / no qual ele estava seguindo links simbólicos ao descer de diretórios. Foi fixado em 4,3 em 2014.

O

bash não tem o equivalente de zargs ou ksh93 command -x do zsh para dividir as linhas de comando, de modo a evitar os problemas lista de arges muito longos . Em um sistema GNU, você sempre pode usar o GNU xargs para isso:

xargs -r0a <(
  shopt -s dotglob nullglob globstar
  printf '%s
find . -depth -exec touch -h -r "$reference_file" {} +
touch -c -h -r "$reference_file" ..
' "$dir/"{.,..,**} ) touch -c -h -r "$reference_file" --

Agora, provavelmente ainda usaria find aqui. Além do pior desempenho, outro problema com globs é que erros (como acesso negado) ao atravessar a árvore de diretórios são silenciosamente ignorados.

    
por 10.12.2017 / 22:35