我将相机照片存储在带有名称的文件中
192.168.33.16_01_20220723150356205_MOTION_DETECTION.jpg
我想将每个日期的每个文件移动到单独的目录中
我发现了这个命令
find | awk '{print $1, substr($1,20,8)}'
打印文件名和所需目标目录的元组
我可以通过管道将此命令的输出传递给命令吗
mkdir -p $2; mv $1 $2
不知何故?可能与xargs
?
答案1
如果您将所有文件都放在同一目录中,这是一个非常简单的解决方案:
for i in *; do mkdir "${i:17:8}" && mv "$i" "${i:17:8}"; done
答案2
您可以修改awk
程序以输出 shell 命令,然后将其通过管道传输到sh
:
find * | awk '{
date=substr($1,20,8)
printf "mkdir -p %s; mv %s %s\n", date, $1, date
}' | sh
如果您的文件名包含空格(或特殊的 shell 字符),上面的代码将不会很好地工作,但只要一切看起来像您在问题中显示的那样,它就会正常工作。
答案3
在您的示例中,您给出了192.168.33.16_01_20220723150356205_MOTION_DETECTION.jpg
& 表示,在awk
,中substr($1,20,8)
为您提供了 Date ,但这与给定的文件名不匹配。
此外,IP 可以更改并具有更多(或更少)数字,例如 192.168.33.16 和 192.168.133.116(和 192.168.3.6),并且硬编码到起始位置 20 并不好。
因此,最好使用分隔符“_”进行拆分,这适用于所有 IP 案例。
现在,当我们有了日期时,我们只想获取 8 个字符,而忽略时间。这些是最左边的角色。
我们还希望仅处理 jpg 文件并仅在目录不存在时才创建 mkdir。
使用 Perl 所有这一切都很简单:
@files_list = <*_*_*.jpg> ; # Process only *.jpg files having atleast 2 "_"
for $one_file (@files_list) {
@items = split("_",$one_file) ; # $items[0] = IP ; $items[2] = Date
$D = substr($items[2],0,8) ; # take only 8 left most Characters from Date
unless (-e "$D") {
system ("mkdir $D") ; # mkdir when the Directory is not existing
}
system ("mv $one_file $D\\$one_file") ; # move file to Directory
}
这已经很强大了,但是我们可以添加更多检查(例如,确保文件名包含_MOTION_DETECTION
且文件名中只有 4 个“_”字符并确保 mkdir 成功并确保 mv 成功),以防万一必要的。像这样的增强功能在 Perl 中也很容易实现!
用法:
从包含 jpg 文件的目录中执行此 Perl 脚本。
所有符合给定条件的 jpg 文件都将按日期移动到目录中。
其他 jpg 文件和所有其他文件将保持不变。
答案4
在我看来,你可以把
mkdir -p $2; mv $1 $2
在脚本中,使脚本可执行并通过管道输入该脚本
find -type f -not -name script.sh | awk '{print $1, substr($1,20,8)}'|xargs ./script.sh
这样您就可以使用已经编写的内容。
或者如果你不需要脚本,你可以按照你所说的使用 xargs 。
find -type f| awk '{print $1, substr($1,20,8)}'|xargs -l bash -c 'mkdir -p $1;mv $0 $1'