使用特定方案重命名文件

时间:2018-12-12 22:49:41

标签: bash

我有一个FTP文件夹,用于接收来自远程摄像机的文件。相机将视频文件名始终存储为./rec_YYYY-MM-DD_HH-MM.mkv。视频文件全部存储在同一个文件夹中,即FTP服务器的根文件夹。

我需要使用这种新方案将这些文件移动到另一个文件夹:

  • 从文件名中删除rec_
  • 将日期格式更改为DD-MM-YY
  • 从文件名中删除日期,而是将其设置为文件夹,该文件将与同一日期中的所有其他文件一起存储在其中。
  • 最终文件路径为:./DD-MM-YYYY/HH-MM.mkv
  • 该过程将继续处理所有文件,并将它们放入与创建日期对应的文件夹中。

总结:./rec_YYYY-MM-DD_HH-MM.mkv >> ./DD-MM-YYYY/HH-MM.mkv。相同的内容应适用于同一文件夹中的所有文件。

由于我无法直接通过相机实现此操作,因此需要使用正在接收文件的服务器上的Bash来完成。

到目前为止,我得到的是脚本,它将获得文件的创建日期并使用它来创建文件夹,然后根据创建时间获得创建时间来使用新名称移动文件。:

for f in *.mp4
do
    mkdir "$f" "$(date -r "$f" +"%d-%m-%Y")"
    mv -n "$f" "$(date -r "$f" +"%d-%m-%Y/%H-%M-%S").mp4"
done

我得到以下输出(带有测试文件1.mp4):

  • 它根据文件的创建日期创建文件夹;
  • 它将文件重命名为其创建时间;
  • 然后,它返回mkdir: cannot create directory ‘1.mp4’: File exists
  • 如果有两个或更多文件,则仅一个文件会按照说明进行重命名和移动。其他的保持不变,终端返回:

mkdir: cannot create directory ‘1.mp4’: File exists mkdir: cannot create directory ‘2.mp4’: File exists mkdir: cannot create directory ‘12-12-2018’: File exists

有人可以帮我吗?更好的建议?谢谢!

4 个答案:

答案 0 :(得分:1)

如果您Git Project B,则可以使用以下脚本

cd /to/some/directory/containing_your_files

请注意①我尚未交换年月日,如果您确实需要进行交换,则可以提取诸如#!/usr/bin/env bash for f in rec_????-??-??_??-??.m{p4,kv} ; do dir=${f:4:10} # skip 4 chars ('rec_') take 10 chars ('YYYY_MM_DD') fnm=${f:15} # skip 15 chars, take the remainder test -d "$dir" || mkdir "$dir" mv "$f" "$dir"/"$fnm" done 等的年,并且②这种参数替换方法是Bash- ism,例如,它在year=${dir::4}中不起作用。

答案 1 :(得分:1)

老实说,我只会使用Perl或Python。这是将它们嵌入到Shell脚本中的方法。

这是一个Perl脚本,它不使用任何库,甚至不包含Perl附带的库(因此它可以在CentOS之类的发行版中使用,而无需额外的软件包,而该软件包不随整个Perl库一起提供)。 perl脚本为每个文件启动一个新进程以执行复制。

perl -e '

while (<"*.m{p4,kv}">) {
    my $path = $_;
    my ($prefix, $year, $month, $day, $hour, $minute, $ext) = 
        split /[.-_]/, $path;
    my $sec = q[00];
    die "unexpected prefix ($prefix) in $path"
        unless $prefix eq q[rec];
    die "unexpected extension ($ext) in $path"
        unless $ext eq q[mp4] or $ext eq q[mkv];
    my $dir = "$day-$month-$year";
    my $name = "$hour-$min-$sec" . q[.] . $ext;
    my $destpath = $dir . q[/] . $name;
    die "$dir . $name is unexpectedly a directory" if (-d $dir);
    system("cp", "--", $path, $destpath);
}
'

这是一个Python示例,它与Python 2或Python 3兼容,但确实使用了标准库。 Python脚本不会产生任何其他进程。

python3 -c '
import os.path as path
import re
from glob import iglob
from itertools import chain
from os import mkdir
from shutil import copyfile

for p in chain(iglob("*.mp4"), iglob("*.mkv")):
  fields = re.split("[-]|[._]", p)
  prefix = fields[0]
  year   = fields[1]
  month  = fields[2]
  day    = fields[3]
  hour   = fields[4]
  minute = fields[5]
  ext    = fields[6]
  sec    = "00"
  assert prefix == "rec"
  assert ext in ["mp4", "mkv"]
  directory = "".join([day, "-", month, "-", year])
  name = "".join([hour, "-", minute, "-", sec, ".", ext])
  destpath = "".join([directory, "/", name])
  assert not path.isdir(destpath)
  try:
    mkdir(directory)
  except FileExistsError:
    pass
  copyfile(src=p, dst=destpath)
'

最后,这是一个bash解决方案。它使用-._分割路径,然后通过在函数内部索引到$@中来提取各种子字段。索引技巧是可移植的,尽管变量上的正则表达式替换是bash扩展。

#!/bin/bash


#   $1  $2  $3 $4 $5 $6 $7  $8
# path  rec YY MM DD HH MM ext
process_file() {
  mkdir "$5-$4-$3" &> /dev/null
  cp -- "$1" "$5-$4-$3"/"$6-$7-00.$8"
}

for path in *.m{p4,kv}; do
    [ -e "$path" ] || continue
    # NOTE: two slashes are needed in the substitution to replace everything
    # read -a ARRAYVAR <<< ... reads the words of a string into an array
    IFS=' ' read -a f <<< "${path//[-_.]/ }"
    process_file "$path" "${f[@]}"
done

答案 2 :(得分:0)

#!/bin/bash

USER_HOME=$(getent passwd $SUDO_USER | cut -d: -f6)

fn_1 () {
  for f in $USER_HOME/FTP/*.mkv
  do
    mv $f `echo $f | cut -c 29-`
  done
}

fn_2 () {
  for x in $USER_HOME/FTP/*.mkv
  do
    mkdir -p "$(date -r "$x" +"$USER_HOME/FTP/Camera1/%d-%m-%Y")"
    mv -n "$x" "$(date -r "$x" +"$USER_HOME/FTP/Camera1/%d-%m-%Y/")"
  done
}

fn_1
fn_2

我已经谈到了这一点。它似乎正在工作,但是输出仍然很差:

date: '/home/pi/FTP/*.mkv': No such file or directory
mkdir: cannot create directory ‘’: No such file or directory
date: '/home/pi/FTP/*.mkv': No such file or directory
mv: cannot stat '/home/pi/FTP/*.mkv': No such file or directory

这是我回显命令所得到的:

enter image description here

建议?

答案 3 :(得分:-1)

您的问题是:mkdir创建了文件夹,但是您要提供用于创建文件夹的文件名。

如果要使用fileName创建文件夹,请使用不带扩展名的文件。

问题是您试图使用已经存在的文件名创建文件夹

enter image description here