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.
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.
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 '%sfind . -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.