Mover o nome do arquivo de várias extensões em outro diretório

4
#!/bin/bash
# script to find and move files

SOURCE=/DRIVE2/folder/
DESTDIR=/DRIVE/new3/

MOVEFILES=(mpg avi m4v mp4 3gp mpeg MOV) 
# this line above is not working, its only reading the first extension

find $SOURCE -type f -name *.$MOVEFILES -print | xargs -i mv -v "{}" $DESTDIR 

Vocês podem me ajudar com meu roteiro de bash? A parte $MOVEFILES do meu script não está funcionando. Está lendo apenas a primeira extensão que coloquei, que é mpg . O resto está sendo ignorado. Qual é a maneira correta de escrever essa linha?

Também é possível incluir o diretório de digamos /DRIVE2/folder1/folder2/folder3/folder4/file.ext move para /DRIVE/folder3/folder4/file.ext

    
por jay six 13.11.2015 / 20:20

4 respostas

3

Usando find com -regex

MOVEFILES=".*\.\(mpg\|avi\|m4v\)"
find "$SOURCE" -type f -regex "$MOVEFILES" -exec mv {} "$DESTDIR" \;

Você também pode usar -iregex em vez de -regex para correspondências insensíveis a maiúsculas e minúsculas como AvI e assim por diante.

Todo o \ parece feio, eu sei. -regextype posix-extended , como usado em resposta @Murus , parece melhor.

    
por A.B. 13.11.2015 / 20:30
6

Você provavelmente deve usar -regex em vez de -name - com -name , cada extensão precisará de um teste -name em separado:

find .. -name '*.mp4' -name '*.avi' ...

Em vez disso:

find -regextype posix-extended ... -regex '.*\.(mp4|avi|...)' ...

Dado seu array, faça (descartando o xargs desnecessário):

find "$SOURCE" -regextype posix-extended  -type f -regex ".*\.($(IFS="|"; echo "${MOVEFILES[*]}"))" -exec mv -t "$DESTDIR" {} +

IFS="|"; echo "${MOVEFILES[*]}" é uma maneira de imprimir todos os elementos na matriz MOVEFILES separados por | .

$MOVEFILES por si só é o primeiro elemento na matriz MOVEFILES .

    
por muru 13.11.2015 / 20:34
5

Você pode fazer isso usando apenas o shell ( bash ):

shopt -s extglob globstar nullglob 
mv -t /destination **/*(*.mpg|*.m4v|*.mpeg|*.mp4|*.avi|*.3gp|*.MOV)
  • Primeiro, precisamos definir algumas opções de shell

  • extglob nos permitirá fazer correspondência estendida de padrões para nomes de arquivos

  • globstar , depois de ativar isso, usando ** , podemos percorrer os subdiretórios para pesquisar os arquivos

  • nullglob resultará em uma string nula se nenhum nome de arquivo for correspondido por nossos padrões fornecidos, em vez dos próprios padrões

  • Agora, *(*.foo|*.bar) é um padrão extglob que corresponderá a zero ou mais ocorrências de *.foo ou *.bar

  • Então, combinado, **/*(*.mpg|*.m4v|*.mpeg|*.mp4|*.avi|*.3gp|*.MOV) nos levará os arquivos a serem movidos

  • mv -t /destination **/*(*.mpg|*.m4v|*.mpeg|*.mp4|*.avi|*.3gp|*.MOV) moverá os arquivos para o /destination .

Exemplo:

$ tree 
.
├── dest
├── foo
│   ├── bar
│   │   ├── baz.md
│   │   ├── egg.3gp
│   │   └── egg.mp4
│   ├── baz.txt
│   ├── spam.avi
│   └── spam.mp3
├── spamegg.MOV
└── spamegg.txt


$ shopt -s extglob globstar nullglob 

$ mv -t dest/ **/*(*.mp3|*.mp4|*.avi|*.3gp|*.MOV)

$ tree 
.
├── dest
│   ├── egg.3gp
│   ├── egg.mp4
│   ├── spam.avi
│   ├── spamegg.MOV
│   └── spam.mp3
├── foo
│   ├── bar
│   │   └── baz.md
│   └── baz.txt
└── spamegg.txt
    
por heemayl 14.11.2015 / 00:50
2
O comando

find permite definir várias condições com -o flag e você realmente não precisa de xargs , você pode usar -exec . Pessoalmente, eu mudaria seu script para

#!/bin/bash
# script to find and move files

SOURCE=/DRIVE2/folder/
DESTDIR=/DRIVE/new3/


find "$SOURCE" -type f \( -name -o "*.mpg" -o -name "*.avi" -o -name "*.m4v" -o -name "*.mp4" -o -name "*.3gp"  -o -name "*.mpeg" -o -name "*.MOV" \) -exec mv -t "$DESTDIR" {} +

Outra abordagem seria com um loop for, em que trabalhamos individualmente em cada extensão

for EXT in ${MOVEFILES[@]}; do find "$SOURCE" -type f -name "*.$EXT" -exec mv -t "$DESTDIR" {} +   ; done
    
por Sergiy Kolodyazhnyy 13.11.2015 / 20:34

Tags