使用特定方案重命名文件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用特定方案重命名文件相关的知识,希望对你有一定的参考价值。

我有一个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

我得到这个输出(使用testfile 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

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

答案

老实说,我只会使用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
另一答案

如果你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

注意①我没有交换年份和日期,如果你绝对需要进行交换,你可以提取这样的年份,year=${dir::4}等,②这种参数替换方法是Bash-ism,例如,它没有在dash工作。

另一答案
#!/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

建议?

另一答案

你的问题是:mkdir创建文件夹,但你给文件夹创建文件名。

如果要使用fileName创建文件夹,请在不使用扩展名的情况下使用它。

问题是您正在尝试使用现有的fileName创建文件夹

enter image description here

以上是关于使用特定方案重命名文件的主要内容,如果未能解决你的问题,请参考以下文章

根据另一列中的元素重命名特定列元素

重命名现有文件名

在代码上重命名 Android 文件夹

如何找到跨文件重命名和重新排序添加特定 Gradle 构建依赖项的 Git 提交?

按特定条件复制和重命名 - 批量

sh 批量重命名文件删除特定字符