我有一个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
有人可以帮我吗?更好的建议?谢谢!
答案 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
这是我回显命令所得到的:
建议?
答案 3 :(得分:-1)