我的目标是对目录中最后修改的文件以秒为单位的门控时间。
我有一个名称中有空格的目录,想用脚本stat
它。对于终端,我只需使用:
sudo stat -c %Y /var/www/pre/data/jko/files/My\ Files
并且工作完美。
在我的 bash
脚本中,我从目录 /var/www/pre/data/jko/files/
中一个一个地读取文件(这是在 while 循环中)
touch tempFile.txt
#ls sort by last modified date
sudo ls -rt /var/www/pre/data/$line/files/ > tempFile.txt
# read newest file
outputFile=$(tail -1 tempFile.txt)
# replace all spaces with "\ " sign
outputFile=$(echo ${outputFile// /"\ "})
outputDirectoryToFile=/var/www/pre/data/$line/files/$outputFile
echo $outputDirectoryToFile
expr `sudo date +%s` - `sudo stat -c %Y $outputDirectoryToFile`
如果我用 bash script.sh
触发这个脚本,我得到了
/var/www/pre/data/jko/files/My\ Files //line from echo
stat: cannot stat '/var/www/pre/data/jko/files/My\': No such file or directory
stat: cannot stat 'Files': No such file or directory
expr: syntax error
或者有更简单的解决方案
最佳答案
正确、高效地找到目录中的最新文件
{ read -r -d ' ' mtime && IFS= read -r -d '' filename; } \
< <(find /directory -type f -printf '%T@ %p\0' | sort -z -r -n)
...会将最近修改的文件的时间(以秒为单位)放入 shell 变量 mtime
中,并将此文件的名称放入 shell 变量 filename
.
此外,它甚至可以处理具有令人惊讶或故意恶意名称的文件——名称中带有换行文字的文件名、带有 glob 字符的文件名等。我对这个习惯用法及其工作原理有更完整的解释 here .
为什么您的原始代码不起作用
现在,您的原始代码有什么问题?简而言之:文字引用不能代替句法引用。让我们来看看这意味着什么。
在 /var/www/pre/data/jko/files/My\Files
中,反斜杠是 syntactic:这是 shell 语法。当您运行 stat/var/www/pre/data/jko/files/My\Files
时,结果是一个系统调用,如下所示:
execv("/usr/bin/stat", "stat", "/var/www/pre/data/jko/files/My Files")
请注意反斜杠是如何消失的?这是因为 shell 在解析字符串时消耗了它。
以下都是完全相同的:
# each of these assigns the same string to the variable named s
s=Hello\ World
s=Hello" "World
s='Hello World'
...它们可以展开如下:
# this passes the *exact* contents of that variable as an argument to stat, and thus tries
# to stat a file named Hello World (no literal quotes in the name):
stat "$s"
在上面,引号又是句法——它们告诉 shell 不要将变量扩展的结果拆分成多个单独的词或将其评估为一个 glob——不是 < em>literal,在这种情况下,它们将作为参数的一部分传递给 stat
。
那么,当您运行 s=${s///'\'}
时会发生什么?您正在将 literal 反斜杠放入数据中。
此后:
s="Hello World"
s=${s// /'\ '} # change string to 'Hello\ World'
stat "$s" # try to stat a file named 'Hello\ World', with the backslash
如果在展开式中省略句法双引号会怎样?它甚至更丑陋:
s="Hello World"
s=${s// /'\ '} # change string to 'Hello\ World'
stat $s # try to stat a file named 'Hello\', and a second file named 'World'
那是因为不带引号的展开并没有贯穿所有的 shell 解析步骤;它只做字段拆分和全局扩展。
关于linux - Bash 脚本无效空格符号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38592536/