我有一个目录,里面有 GB(大约 8GB)的单个小文件。我想按日期将它们组织到目录中。创建日期是文件名的一部分。
以下是文件名的示例:
4RCPBlockCoverLtrednalaserfalse07-10-2012-11-50-14-656.doc.gz
我想要像这样设置文档目录:
docs_by_date
2013
01
02
03
04
如果目标目录不存在,则应创建该目录。验证复制成功后,应删除源文件。
我并不是 bash 的超级专家,很多符号我仍然不知道它们的含义,因此,如果能解释一下脚本的作用就更好了。
答案1
我假设对于文件07-10-2012-11-50-14-656.doc.gz
,您希望它按年份(即2012
)和月份(即10
)排序。
#!/usr/bin/env bash
# This is the preferred way of invoking a bash script, and is better than #!/bin/bash for reasons of portability.
# To use the script, make it executable with `chmod u+x /path/to/script`
# Then run this script with `/path/to/script /path/to/original/files /path/to/docs_by_date`
# Let's set up some path variables. This script will transfer files from the directory specified by the first argument to the directory specified by the second.
pathtooriginalfiles=$1
pathtotarget=$2
# Lets iterate over the files in the original directory, by listing all non-invisible files with $(ls ${pathtooriginalfiles}), and repeating the block with $i changing each time.
for i in $(ls "${pathtooriginalfiles}"); do
# Find the matching parts of the filename that specify the date by echoing then piping the variable to sed. The regex part looks for "everything at the beginning" ^.*, followed by two iterations of digits [0-9]{2}, followed by four iterations of digits, etc. before ending with .doc.gz. It then replaces this entire string with what matches between () using the \1 variable, i.e. the year or month.
year=$(echo -n ${i}| sed -r 's/^.*[0-9]{2}-([0-9]{4})-[0-9]{2}-[0-9]{2}-[0-9]{2}-[0-9]{3}\.doc\.gz$/\1/')
month=$(echo -n ${i}| sed -r 's/^.*([0-9]{2})-[0-9]{4}-[0-9]{2}-[0-9]{2}-[0-9]{2}-[0-9]{3}\.doc\.gz$/\1/')
# Create the directory if it doesn't exist already, then copy into it.
mkdir -p "${pathtotarget}/${year}/${month}"
cp "${pathtooriginalfiles}/${i}" "${pathtotarget}/${year}/${month}"
done
另外,我还没有完全按照您的要求编写代码。您说它应该测试文件是否存在,然后自动删除它们。相反,这个脚本只是复制它们,而保留原始文件。我建议您自己手动“测试”它,以确保它按照您认为应该的方式运行,而不是依赖脚本自己执行该操作。(复制部分中的任何错误都可能在检查部分中复制。)如果您真的希望脚本删除原始文件,那么只需将该cp
部分更改mv
为。(无论如何,我觉得 mv 比复制和删除更干净。一个原因是它cp
没有校验和,尽管您可以使用rsync -a
它来代替。
答案2
好的,看来我已经明白了,这要归功于你的帮助!
这是一个简单的错误!有 7 个字段,而不是 6 个!如果您查看原始文件名:
4RCPBlockCoverLtrednalaserfalse07-10-2012-11-50-14-656.doc.gz
- 粗体部分就是我们要的。年份 (2012) 和月份 (7)。在脚本中,它将 10(介于 07 和 2012 之间)视为第一个字段!我所做的就是在它们之间添加 [0-9]{2},然后,它就成功了!
这是您给我的脚本,然后您可以看到我如何“编辑”它。
非常感谢你的帮助!拯救了我一天!
/usr/bin/env bash 原始文件路径=$1 路径到目标=$2 对于我在 $(ls"${pathtooriginalfiles}"); 中执行 年 = $ (echo -n $ {i} | sed -r 's/^.*[0-9]{2}-[0-9]{2}-([0-9]{4})-[0-9]{2}-[0-9]{2}-[0-9]{2}-[0-9]{1,3} \.doc\.gz$/\1/') 月=$(echo -n ${i}| sed -r 's/^.*([0-9]{2})-[0-9]{2}-[0-9]{4}-[0-9]{2}-[0-9]{2}-[0-9]{2}-[0-9]{1,3}\.doc\.gz$/\1/') 回显$年$月 mkdir -p "${pathtotarget}/${year}/${month}" ls -l $目标路径 cp -auv "${pathtooriginalfiles}/${i}" "${pathtotarget}/${year}/${month}/" 完毕
对我个人而言,{1,3} 之间的“,”是关键。
并且 cp 字符串 ${month}/" 末尾的 "/" 也是关键。