在另一个目录中移动多个扩展文件名

在另一个目录中移动多个扩展文件名
#!/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 

你们能帮我修改一下我的 bash 脚本吗?$MOVEFILES我的脚本的一部分不起作用。它只读取我放在那里的第一个扩展名,即mpg。其余的都被忽略了。该如何正确编写该行?

另外是否可以包括它的来源目录,比如说 /DRIVE2/folder1/folder2/folder3/folder4/file.ext移动到/DRIVE/folder3/folder4/file.ext

答案1

您可能应该使用--regex而不是-name- -name,每个扩展都需要单独的-name测试:

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

反而:

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

给定你的数组,执行(放弃不必要的xargs):

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

IFS="|"; echo "${MOVEFILES[*]}"是一种打印数组中每个元素的方法,MOVEFILES用 分隔|

$MOVEFILES其本身只是MOVEFILES数组中的第一个元素。

答案2

你可以只使用 shell ( bash) 来做到这一点:

shopt -s extglob globstar nullglob 
mv -t /destination **/*(*.mpg|*.m4v|*.mpeg|*.mp4|*.avi|*.3gp|*.MOV)
  • 首先我们需要设置一些 shell 选项

  • extglob将使我们能够对文件名进行扩展模式匹配

  • globstar,启用此功能后,我们可以通过使用**遍历子目录来搜索文件

  • nullglob如果没有文件名与给定的模式匹配,而不是与模式本身匹配,则会导致空字符串

  • 现在,*(*.foo|*.bar)是一个extglob匹配零次或多次出现的*.foo模式*.bar

  • 结合起来,**/*(*.mpg|*.m4v|*.mpeg|*.mp4|*.avi|*.3gp|*.MOV)我们可以得到要移动的文件

  • mv -t /destination **/*(*.mpg|*.m4v|*.mpeg|*.mp4|*.avi|*.3gp|*.MOV)会将文件移动到/destination

例子:

$ 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

答案3

使用find-regex

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

您还可以使用-iregex而不是-regex来进行不区分大小写的匹配,例如AvI等等。

我知道,所有的东西\看起来都很丑。-regextype posix-extended,就像@Murus 回答,變得更好看。

答案4

find命令允许使用-o标志设置多个条件,并且您实际上不需要xargs,您可以使用-exec。就我个人而言,我会将您的脚本更改为

#!/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" {} +

另一种方法是使用 for 循环,我们分别处理每个扩展

for EXT in ${MOVEFILES[@]}; do find "$SOURCE" -type f -name "*.$EXT" -exec mv -t "$DESTDIR" {} +   ; done

相关内容