当我从 Shotwell 中的相机导入图片时,它也会导入视频剪辑。这有点烦人,因为我想将视频存储在另一个文件夹中。我尝试编写一个 bash 命令来执行此操作,但没有成功。
我需要一个满足以下要求的命令:
- 找到目录结构中扩展名为 .jpg、.png、.gif 或 .xcf(不区分大小写)的所有文件。
- 将所有这些文件移动到目标目录中,无论文件名或目录路径是否包含空格或特殊字符。
任何帮助,将不胜感激!
编辑:我在 Ubuntu 中使用默认 shell,这意味着某些命令是别名的,等等。
编辑2:我自己尝试过(不是复制部分,只是文件列表部分)。我打开 extglob 并运行以下命令:
$ ls -R /path | awk '
/:$/&&f{s=$0;f=0}
/:$/&&!f{sub(/:$/,"");s=$0;f=1;next}
NF&&f{ print s"/"$0 }'
这列出了所有内容。我尝试在它的末尾使用 grep,但不知道如何让它与我给出的模式不匹配。 extglob 开关对 grep 没有多大帮助,尽管它对其他命令有帮助。
答案1
您可以使用find
查找目录树中与某些特定测试匹配(或不匹配)的所有文件,然后对它们执行某些操作。对于这个特定问题,您可以使用:
find -type f ! \( -iname '*.png' -o -iname '*.gif' -o -iname '*.jpg' -o -iname '*.xcf' \) -exec echo mv {} /new/path \;
这将搜索限制为常规文件 ( -type f
),然后限制为名称 ( ) 不具有任何大小写!
扩展名( ) 或 ( )的文件,依此类推。所有扩展都分组为 之间的单个条件。对于每个匹配的文件,它运行一个命令 ( ),将文件移动到目录中,文件名将代替, 插入到目录中。表示命令已结束。*.png
-iname '*.png'
-o
*.gif
\( ... \)
-exec
{}
/new/path
\;
find
名称替换发生在程序执行代码内部,因此空格和其他特殊字符并不重要。
如果您想在 Bash 中执行此操作,您可以使用 Bash 的扩展模式匹配功能。这些也需要shopt extglob
开启globstar
。在这种情况下,使用:
mv **/!(*.[gG][iI][fF]|*.[pP][nN][gG]|*.[xX][cC][fF]|*.[jJ][pP][gG]) /new/path
这将匹配子目录 ( ) 中与任意字符大小写组合中的 、 等不匹配的所有文件,并将它们移动到新路径中**
。扩展是由 shell 执行的,因此空格和特殊字符不再重要。*.gif
*.png
上面假设所有文件都位于子目录中。如果没有,您可以重复后面的部分**/
以包含当前目录。
类似的功能还有zsh
和其他 shell,但您已表明您正在使用 Bash。
(进一步说明:解析ls
从来都不是一个好主意 - 只是不要尝试它。)
答案2
你使用 Ubuntu,所以你会找到 GNU,尝试:
find . -maxdepth 1 ! -iregex ".*\.\(jpg\|png\|gif\|xcf\)$" -exec mv -- -t /path/to/newdir "{}" +
-iregex
使用正则表达式查找文件名,但不区分大小写,!
否定正则表达式。-exec command +
运行文件匹配命令。就像使用find -print0
with一样xargs -0
。使用此功能,我们可以移动一个命令找到的多个文件mv
,因此调用命令的总数小于匹配文件的数量。-maxdepth 1
限制find
仅在当前目录中搜索,如果要递归,请将其删除。
答案3
没有必要把这个事情搞得太复杂!为什么不只是:
mkdir ../temp
mv *.{jpg,png,gif,xcf} ../temp/
mv * /desired/target/directory/
mv ../temp/* .
rmdir ../temp
当然,这不适用于整个目录树,仅适用于一个平面文件目录。