#!/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