我有一个目录“New Movies”,其中包含 200 多个子目录“电影名称(年份)”。子目录“电影名称(年份)”包含一个视频文件(avi/mkv)和几个相关的 jpg/xml 文件。
我需要将包含至少 180 天的视频文件的所有目录移动到另一个目录。
例如:
新电影/电影 A(年)将包含 movie.mkv、folder.jpg 和 movie.xml,我想将它们移动到其他地方的同名子目录,并且所有文件都存在且完好无损。
在本网站的其他地方查看后,我尝试过:
cd "/mnt/user/New Movies/"
find -type f \( -name "*.avi" -or -name ".*mkv" \) -mtime +180 -exec sh -c 'mv "${0%/*}" /mnt/user/Movies' {} \;
该命令成功地将第一个子目录和所有文件移动到新目录,但是此后的每个操作都会返回错误
find: './Movie B (year)': No such file or directory
find: './Movie C (year)': No such file or directory
依此类推,浏览“新电影”下包含的所有目录,无论它们是否要移动。
答案1
不要-exec mv
当前正在检查的目录find
。find
当你这样做时,似乎会感到困惑。
解决方法:首先找到目录,然后移动它们。
cd "/mnt/user/New Movies/"
find -type f \( -name "*.avi" -or -name ".*mkv" \) -mtime +180 \
-printf "%h\0" | xargs -0 mv -t /mnt/user/Movies
解释:
-printf
根据格式字符串打印匹配项。%h
打印匹配的路径部分。这对应于"${0%/*}"
您命令中的 。\0
使用空字符分隔项目。这只是为了防止文件名包含换行符。xargs
从管道收集输入,然后执行附加输入的参数。-0
告诉 xargs 期望输入以空分隔而不是换行分隔。mv -t <target>
允许mv
在调用时将所有源参数附加在末尾。
请注意,这仍然不是绝对安全的。一些奇怪的调度程序计时与管道缓冲区相结合仍然可能导致在移出目录mv
之前执行。find
为了防止这种情况,你可以这样做:
cd "/mnt/user/New Movies/"
find -type f \( -name "*.avi" -or -name ".*mkv" \) -mtime +180 \
-printf "%h\0" > dirstomove
xargs -0 mv -t /mnt/user/Movies < dirstomove
背景说明:
我想你的情况find
如下:
find
遍历目录/mnt/user/New Movies/
。在那里,它会记录其缓存中的可用目录。find
使用系统调用遍历到子目录之一chdir(subdirname)
。- 在里面
find
找到一个通过过滤器的电影文件。 find
mv
使用给定的参数执行。mv
将目录移动到/mnt/user/Movies
.find
使用系统调用返回父目录chdir(..)
,该调用现在指向/mnt/user/Movies
而不是/mnt/user/New Movies/
find
很困惑,因为它找不到之前记下的目录并抛出很多错误。
这个假设是基于这个问题的答案:find -exec mv 在第一次执行后停止。我不知道为什么find
在这种情况下会停止工作并在您的情况下抛出错误。不同版本的find
可能是解释。
答案2
设置IFS环境变量,IFS=$(echo -en "\n\b");
以便外壳程序将根据换行符而不是空格来分隔项目。
此外,这-exec sh -c 'mv "${0%/*}" /mnt/user/Movies' {} \;
也很奇怪。如果我没记错的话简化为-exec mv {} /mnt/user/Movies \;