
Eu tenho um grande número de arquivos pequenos, f, organizados em uma estrutura de diretórios como esta:
/A/B/C/f
Existem 11 diretórios no nível A, cada um com cerca de 100 diretórios no nível B, cada um com cerca de 30 diretórios no nível C, cada um com um arquivo f.
Como movo todos os arquivos para um nível acima? Por exemplo, dado este conjunto de arquivos...
/A/B/C/f1
/A/B/C/f2 /A
/B/C/f3
/A/B/C/f4
Quero que o diretório /A/B/
contenha 4 arquivos, de f1 a f4. A remoção dos diretórios C não é necessária.
Espero que este seja um problema resolvido, possivelmente envolvendo find
, xargs
e whatnot
. Alguma ideia?
Saúde,
James
Responder1
É bastante simples com GNU find (como encontrado no Linux) ou qualquer outro find que suporte -execdir
:
find A -type f -execdir mv -i {} .. \;
Com um padrão find
:
find A -type f -exec sh -c 'mv -i "$1" "${1%/*}/.."' sh {} \;
Com zsh:
zmv -Q -o-i 'A/(**/)*/(*)(.)' 'A/$1$2'
Se a estrutura de diretórios sempre tiver o mesmo nível de aninhamento, você não precisará de nenhuma travessia recursiva (mas primeiro remova os diretórios vazios):
for x in */*; do; echo mv -i "$x"/*/* "$x"/..; done
Responder2
Para esse conjunto de arquivos, isso faria:
$ cd /A/B/C/
$ mv ./* ../
Mas espero que o seu problema seja um pouco mais complicado... Não posso responder... Não tenho muita certeza de como está a sua estrutura de diretórios... Poderia esclarecer?
Responder3
Meu primeiro palpite é
$ find A -type f -exec mv {} .. \;
contanto que você não especifique, -depth
tudo bem. Eu NÃO tentei, então teste primeiro antes de se comprometer.
Responder4
Se você deseja mover apenas arquivos que estão em diretórios folha (ou seja, não deseja mover /A/B/file
para /A
if B
contém subdiretórios), aqui estão algumas maneiras de fazer isso:
Ambos exigem isso
leaf ()
{
find $1 -depth -type d | sed 'h; :b; $b; N; /^\(.*\)\/.*\n\1$/ { g; bb }; $ {x; b}; P; D'
}
shopt -s nullglob
Este funciona:
leaf A | while read -r dir
do
for file in "$dir"/*
do
parent=${dir%/*}
if [[ -e "$parent/${file##*/}" ]]
then
echo "not moved: $file"
else
mv "$file" "$parent"
fi
done
done
Isso será mais rápido, mas não gosta de diretórios de origem vazios:
leaf A | while read -r dir
do
mv -n "${dir}"/* "${dir%/*}"
remains=$(echo "$dir"/*)
[[ -n "$remains" ]] && echo "not moved: $remains"
done