如何根据这些文件的名称将文件分发到每个目录?

如何根据这些文件的名称将文件分发到每个目录?

我将相机照片存储在带有名称的文件中

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'

相关内容