AAa*_*Aaa 10 scripting bash timestamps files
可能的重复:
用于移动最旧文件的 Shell 脚本?
我有一个备份目录,用于存储x需要备份的其他目录。我需要在另一个目录移动到备份之前运行的东西,它会检查目录数量x是否达到,如果达到,它将删除最旧的目录。
它应该在bash脚本中完成。
Sor*_*gal 20
解析 的输出ls是不可靠的。
相反,用于find定位目录并按sort时间戳对其进行排序。例如:
IFS= read -r -d $'\0' line < <(find . -maxdepth 1 -type d -printf '%T@ %p\0' \
2>/dev/null | sort -z -n)
file="${line#* }"
# do something with $file here
Run Code Online (Sandbox Code Playgroud)
首先,find命令在当前目录(.)中定位所有目录,但不在当前目录(-maxdepth 1)的子目录中,然后打印出:
时间戳很重要。的%T@格式说明-printf符分解为T,表示文件的“上次修改时间”(mtime)和@,表示“自 1970 年以来的秒数”,包括小数秒。
空格只是一个任意的分隔符。文件的完整路径是为了我们以后可以引用它,NULL 字符是一个终止符,因为它是文件名中的非法字符,因此让我们确信我们到达了路径的末尾文件。
我已包含,2>/dev/null以便排除用户无权访问的文件,但会抑制有关它们被排除的错误消息。
find命令的结果是当前目录中所有目录的列表。该列表通过管道传送到sort其被指示:
-z 将 NULL 视为行终止符而不是换行符。-n 按数字排序由于自 1970 年以来的秒数总是上升,我们想要时间戳是最小数字的文件。第一个结果sort将是包含最小编号时间戳的行。剩下的就是提取文件名。
find,sort管道的结果通过进程替换传递到read,在那里它被读取,就好像它是标准输入上的文件一样。
在read我们将IFS变量设置为空的上下文中,这意味着空格不会被不恰当地解释为分隔符。read被告知-r,它禁用了转义扩展,而-d $'\0',它使行尾分隔符为 NULL,与我们的find,sort管道的输出相匹配。
第一个数据块,代表最旧的目录路径,前面有它的时间戳和一个空格,被读入变量line。接下来,将参数替换与表达式 一起使用#*,它只是将字符串开头到第一个空格(包括空格)的所有字符替换为空。这会去除修改时间戳,只留下文件的完整路径。
此时文件名已存储在其中$file,您可以对它进行任何您喜欢的操作,包括rm -rf "$file".
不。更简单的方法有问题。
如果你使用ls -t和管道到tail你会打破文件名中带有换行符的文件。如果您rm $(anything)然后名称中带有空格的文件将导致损坏。如果您rm "$(anything)"然后名称中带有尾随换行符的文件将导致损坏。
也许在特定情况下,您肯定知道一种更简单的方法就足够了,但是如果可以避免的话,您永远不应该在脚本中编写这样的假设。
#!/usr/bin/env bash
dir="$1"
min_dirs=3
[[ $(find "$dir" -maxdepth 1 -type d | wc -l) -ge $min_dirs ]] &&
IFS= read -r -d $'\0' line < <(find "$dir" -maxdepth 1 -printf '%T@ %p\0' 2>/dev/null | sort -z -n)
file="${line#* }"
ls -lLd "$file"
Run Code Online (Sandbox Code Playgroud)
一个更完整的问题解决方案,因为它首先检查目录计数。