我有数十万个照片文件夹。无论出于什么原因,在导出时,它们都创建了以下几种情况:
2019/01/01
2019/01/01 #2
如何编写一个 Linux 命令(最好可以在 Mac 上运行)来自动移动文件
from
2019/01/01 #2
to
2019/01/01
任何帮助都将不胜感激。这需要适用于任何日期,并合并内容。我苦苦挣扎的地方是,我无法理解如何在没有 # 的情况下将目录获取为原始格式
for dir in *#2/*; do mv "$dir"/* "${dir}"; done
答案1
使用find
和-exec
:
find . -type d -name "* #*" -exec bash -O nullglob -c '
for dir; do
otherdir=${dir/ #*}
if [ -d "$otherdir" ]; then
for file in "$dir"/*; do
mv -vi "$file" "$otherdir"
done
rmdir "$dir" && echo "deleted directory $dir"
else
mv -v "$dir" "$otherdir"
fi
done
' bash {} +
如果后一个目录存在,则此操作会将所有文件从 移动2019/01/01 #2
到2019/01/01
(如果不存在,则#
重命名带有 的文件夹)。如果 中有文件2019/01/01 #2
已存在于另一个文件夹中,则它会请求移动文件的权限。
移动操作完成后,它会尝试删除(现在为空的)文件夹。所有移动/删除操作都处于详细模式。
nullglob
与 for 循环结合启用可确保"$dir"/*
如果目录已为空则不会返回任何文件。
答案2
尝试此操作之前请备份您的文件。这可能会造成破坏...
问题的一部分在于for
,在遍历名称中带有空格的文件夹时使用。您最终会得到一个不一致的列表,因为空格和回车符都是字段分隔符。您需要设置IFS
为仅回车符。(您可以使用find -exec
直接处理文件系统条目,但变得混乱使用嵌套通配符时
这应该可以完成工作,但要注意移动的文件将覆盖目标文件夹中匹配的文件。从上面的根文件夹运行它。
# Set IFS to carriage return only.
IFS='
'
# Find all the matching folders and move the .jpg files out of them to the sibling folder.
for a in $(find . -type d -name *#*); do b=${a::-3}; mv $a/*.jpg $b/; rmdir $a; done
做了一些假设: - 您描述的结构是年/月/日子文件夹。(如果文件夹名称包含\
它会变得更丑陋) - 您只有一些带后缀的文件夹#2
- 您想要在将文件移出后删除 #2 文件夹。
看这里关于如何在 Bash 中使用字符串做更多奇怪的事情……