Localize e mova diretórios com base no tipo de arquivo e na data

1

Eu tenho um diretório "Novos filmes" contendo mais de 200 subdiretórios "Nome do filme (ano)". Os subdiretórios "Movie Name (year)" contém um único arquivo de vídeo (avi / mkv) e vários arquivos jpg / xml relacionados.

Eu preciso mover todos os diretórios contendo um arquivo de vídeo com pelo menos 180 dias para outro diretório.

Por exemplo:

Novos filmes / filme A (ano) conteria movie.mkv, folder.jpg & movie.xml e eu quero movê-los para um subdiretório do mesmo nome em outro lugar com todos os arquivos presentes e intactos.

Depois de procurar em outro lugar neste site, tentei:

cd "/mnt/user/New Movies/"
find -type f \( -name "*.avi" -or -name ".*mkv" \) -mtime +180 -exec sh -c 'mv "${0%/*}" /mnt/user/Movies' {} \;

O comando move com sucesso o primeiro subdiretório e todos os arquivos para sua nova casa, mas todas as operações após essa retornam o erro

find: './Movie B (year)': No such file or directory
find: './Movie C (year)': No such file or directory

e assim por diante, em todos os diretórios contidos em "Novos filmes", independentemente de serem movidos ou não.

    
por Justin 20.08.2013 / 22:10

2 respostas

0

Não -exec mv do diretório que está sendo examinado por find . Parece que find fica confuso quando você faz isso.

Solução alternativa: primeiro encontre os diretórios e mova-os.

cd "/mnt/user/New Movies/"
find -type f \( -name "*.avi" -or -name ".*mkv" \) -mtime +180 \
  -printf "%h
cd "/mnt/user/New Movies/"
find -type f \( -name "*.avi" -or -name ".*mkv" \) -mtime +180 \
  -printf "%h
cd "/mnt/user/New Movies/"
find -type f \( -name "*.avi" -or -name ".*mkv" \) -mtime +180 \
  -printf "%h
cd "/mnt/user/New Movies/"
find -type f \( -name "*.avi" -or -name ".*mkv" \) -mtime +180 \
  -printf "%h%pre%" > dirstomove
xargs -0 mv -t /mnt/user/Movies < dirstomove
" | xargs -0 mv -t /mnt/user/Movies
" > dirstomove xargs -0 mv -t /mnt/user/Movies < dirstomove
" | xargs -0 mv -t /mnt/user/Movies

Explicação:

  • -printf imprime a correspondência de acordo com a string de formatação.
  • %h imprime a parte do caminho da correspondência. Isso corresponde ao "${0%/*}" em seu comando.
  • xargs separa os itens usando o caractere nulo. Esta é apenas uma precaução, caso os nomes de arquivos contenham novas linhas.
  • -0 coleta a entrada do pipe e, em seguida, executa seus argumentos com a entrada anexada.
  • mv -t <target> diz ao xargs para esperar que a entrada seja nula separada em vez de nova linha separada.
  • mv permite que mv seja chamado com todos os argumentos de origem anexados no final.

Observe que isso ainda não é absolutamente seguro. Algum tempo cronometrado do planejador em combinação com buffers de pipe ainda pode fazer com que o find seja executado antes que find seja movido para fora do diretório. Para evitar que você faça isso:

%pre%

Explicação do histórico:

Eu acho que o que acontece com o seu find é o seguinte:

  1. /mnt/user/New Movies/ atravessa o diretório find . Enquanto lá, toma nota dos diretórios disponíveis em seu cache.
  2. chdir(subdirname) atravessa um dos subdiretórios usando a chamada do sistema find .
  3. Por dentro de find encontra um arquivo de filme que passa pelos filtros.
  4. mv executa mv com os parâmetros fornecidos.
  5. /mnt/user/Movies move o diretório para find .
  6. chdir(..) volta ao diretório pai usando a chamada do sistema /mnt/user/Movies , que agora aponta para /mnt/user/New Movies/ em vez de find
  7. find está confuso porque não encontra os diretórios que anotou anteriormente e gera muitos erros.

Essa suposição é baseada na resposta a essa pergunta: find - exec mv pára após o primeiro exec . Eu não sei porque find apenas pára de funcionar nesse caso e gera erros no seu caso. Versões diferentes de %code% podem ser a explicação.

    
por 22.08.2013 / 10:59
0

Defina a variável ambiental IFS como IFS=$(echo -en "\n\b"); , para que o shell separe itens com base em novas linhas em vez de espaços.

Além disso, esse -exec sh -c 'mv "${0%/*}" /mnt/user/Movies' {} \; é bem bizarro. Se não me engano, simplifique para -exec mv {} /mnt/user/Movies \;

    
por 21.08.2013 / 08:04