当名称可以包含空格时,查找第二个最新文件



下面是我的shell脚本。 我需要获取第二个最新的文件大小。 但是当我尝试在脚本下面运行时,我遇到了空间在哪里的问题,它试图将其作为目录/文件打开并给出没有此类文件或目录的错误。

请参阅以下错误。

tokenFileSubstring="/tmp/Anusha/exception_reports/ALIQD022_Active_Facilities with Pending_Fees_*.xls"
newFile=$(echo $tokenFileSubstring | sed "s/ /\ /g")
echo "newfile :: $newFile"
previousFileSize=`ls -lrt $newFile |tail -2 | head -1|awk '{print $5}'`
echo "previous file siz: $previousFileSize"

bash-4.1$ ./basic.sh

newfile ::/tmp/Anusha/exception_reports/AHJ800_Active_Facilities\ with\ Pending_Fees_2019-12-19-22-45-18.xls ls:无法访问/tmp/Anusha/exception_reports/ALIQD022_Active_Facilities:没有这样的文件或目录 ls:无法访问:没有这样的文件或目录 :没有这样的文件或directoryees_2019-12-19-22-45-18.xls

请帮我找到第二个最新的文件大小

如果你有GNU工具,并且你的shell是bash:

#!/usr/bin/env bash
[ -n "$BASH_VERSION" ] || { echo "This script requires bash" >&2; exit 1; }
dir=/tmp/Anusha/exception_reports
pattern='ALIQD022_Active_Facilities with Pending_Fees_*.xls'
{
read -d '' _;  # ignore very latest file entirely
IFS= read -r -d ' ' time
IFS= read -r -d ' ' size
IFS= read -r -d ''  name
} < <(find "$dir" -maxdepth 1 -type f -name "$pattern" -printf '%T@ %s %P' | sort -zrg)
# note that this %()T timestamp formatting operator requires a quite new bash release.
printf 'Second latest file has name %q, size %d, time %(%Y-%m-%d %H:%M:%S)Tn' 
"$name" "$size" "${time%%.*}"

其工作原理如下:

  • find -printf '%T@ %s %P',对于每个文件,发出以下内容:

    • 自纪元(即自 1970 年以来(以来的时间戳(以秒为单位(,后跟一个空格
    • 该文件的大小(您要查找的内容(,后跟一个空格
    • 文件的名称,后跟 NUL 字符。


    这种格式很重要,因为时间戳和大小不能包含空格(因此空格可以安全地分隔它们(——但名称可以包含空格——此外,名称甚至可以包含换行符文字!因此,唯一可以安全用于查找文件名结尾的字符是 NUL,即 UNIX 路径中不可能存在的字符。

  • sort -zrg对由 NUL 分隔的记录(将时间戳视为数字 --g支持浮点,而-n只考虑整数部分(,对由 NUL 分隔的记录(这是-z指定的(。-r以相反的顺序排列,因此最新的文件排在第一位,而第二个最新的文件(您尝试查找的文件(排在第二位。
  • <(...)是一个进程替换,它扩展为输出为...的文件名 - 在本例中为find | sort管道的输出。从该进程替换重定向到前面的另一个<意味着代码块(reads(中的内容将看到进程替换的输出,而不会对使用管道创建的变量范围进行不必要的限制。
  • read -d '' _读取下一个 NUL,将结果放入虚拟变量_(向读者暗示我们不打算读取或使用这些结果(。因此,将其作为处理流的第一项会忽略最新文件。
  • IFS= read -r -d ' ' time将所有内容读入变量time的下一个空格。
  • IFS= read -r -d ' ' size将所有内容读入变量size之后的空间。
  • IFS= read -r -d '' name将所有内容读取到变量name中,直到下一个 NUL 。

。因此,我们能够将最新文件的名称、大小和时间戳收集到单独的变量中,而无需依赖非常不可靠的ls工具。

使用这个答案,我们可以构建另一种方法。如果您认为您需要的文件总是以.xls结尾,我们可以将文件名的开头存储在tokenFileSubstring中,并且仅在ls时使用扩展。

tokenFileSubstring="/tmp/Anusha/exception_reports/ALIQD022_Active_Facilities with Pending_Fees_"
previousFileSize=$(ls -lrt "$tokenFileSubstring"*.xls |tail -2 | head -1|awk '{print $5}')
echo "previous file siz: $previousFileSize"

另外,我不明白你想检索什么ls | tail | head | awk.也许您只需ls | awk就可以达到相同的结果

编辑

您也可以使用以下命令,只需ls | awk,以简化:

previousFileSize=$(ls -lrt "$tokenFileSubstring"*.xls | awk 'BEGIN { n = 1 } { a[n++] = $5 } END { print a[n - 2] }'

最新更新