Como você pode mover (ou copiar) todos os arquivos para um diretório com o mesmo prefixo de nome de arquivo?

9

Usando o Bash

Então, digamos que eu tenha um monte de arquivos colocados aleatoriamente em um diretório pai ~/src, quero pegar todos os arquivos correspondentes a um determinado sufixo e movê-los (ou copiá-los) para um ~/distdiretório.

Vamos supor para esse fim que todos os nomes de arquivos tenham esta convenção de nomenclatura:

<filename_prefix>.<filename_suffix>

Eu descobri que essa era uma maneira rápida de obter todos os arquivos com um determinado arquivo filename_suffixe colocá-los em uma pasta dist:

mkdir ~/dst
find source -name "*.xxx" -exec mv -i {} -t ~/dst \;

Agora, um passo adiante ... como posso usar a saída de find, nesse caso filename, e usar o filename_prefixpara gerar um diretório com o mesmo nome ~/diste depois mover (ou copiar) todos os arquivos com esse prefixo para o diretório apropriado?

mkdir ~/dst
find source -name "*.xrt,*.ini,*.moo" -exec mv -i {} -t ~/dst \;

Essencialmente, como altero o comando acima (ou talvez use outro comando), para criar uma estrutura como esta

(RESULTADO)

~/dist/people/people.xrt
~/dist/games/games.xrt
~/dist/games/games.moo
~/dist/games/games.ini
~/dist/monkeys/monkeys.ini
~/dist/monkeys/monkeys.xrt

de uma árvore de diretórios como esta?

(ENTRADA)

~/src/xrt/people.xrt
~/src/xrt/games.xrt
~/src/conf/games.ini
~/src/pack/monkeys.xrt
~/src/e344/games.moo
~/src/e344/monkeys.moo
~/src/en-us/monkeys.ini
qodeninja
fonte

Respostas:

10

Seria um inferno dizer findo que fazer neste caso.

Melhor usar o shell:

for i in **/*.{xrt,ini,moo}; do
  FILE=$(basename "$i")
  DIR=~/dst/${FILE%.*}
  echo mkdir -p -- "$DIR"
  echo mv -i -t "$DIR" -- "$i"
done

Use shopt -s globstarpara fazer a **glob funcionar (ou use zsh!). E remova echos mais tarde se o comando imprimir o que você deseja.

Stéphane Gimenez
fonte
usando bash é o mesmo?
Qodeninja 6/02/12
@ codeninja shopt -s globstar, veja minha edição. Se houver apenas dois níveis, você poderá usar */*.*e o snippet funcionará em qualquer shell.
Gilles 'SO- stop be evil'
2

trapaça encontrar linha de comando:

find source -name "*.xrt,*.ini,*.moo" -exec env file={} bash -c 'base="$(basename "$file")";dir="dst/${base%.*}";mkdir -p "$dir";cp "$file" "$dir"' \;

na verdade, uma solução alternativa para chamar o script bash no find LOL.

= P

yuyichao
fonte
11
Adivinhe o que acontece se houver um arquivo chamado… happy rm -rf /! Esse tipo de código merece um -1.
Stéphane Gimenez
A sua edição não é suficiente: digamos que você cliked em um link e baixado Yay" rm -rf / "Rox0r.avi, novamente não é como um problema ...
Stéphane Gimenez
(E não há como tornar esse tipo de substituição seguro).
Stéphane Gimenez
11
Ah, talvez seja possível fazer isso de maneira diferente. Parece que as seguintes obras: -exec bash -c 'command which uses "$1"' bash '{}' ';'. Bem, é inútil de qualquer maneira.
Stéphane Gimenez
11
@ StéphaneGimenez feito, bash não é a única coisa a usar. LOL
yuyichao 7/02