【问题标题】:Check if a file exists with a filename containing spaces检查是否存在文件名包含空格的文件
【发布时间】:2017-12-13 07:55:31
【问题描述】:

我正在 Bash 中测试文件是否存在,其中文件名使用 $(printf '%q' "$FNAME") 转义。

使用if [ -f $FNAME ] 总是会产生错误,如下面的注释示例所示。如何测试包含空格和其他字符的文件名?

#!/usr/bin/env bash

# code used in Raspberry Pi Podcasting Jukebox project
# youtube-dl -f 17 --get-filename https://www.youtube.com/watch?v=AgkM5g_Ob-w
# returns "HOW ABUNDANCE WILL CHANGE THE WORLD - Elon Musk 2017-AgkM5g_Ob-w.3gp"

# Purpose: To test if file exists before downloading
# for testing purposes using an existing regular file "abc def ghi"
AFILE="abc def ghi"
TFILE=$(printf '%q' "$AFILE") # Escaping filename using printf
echo $TFILE # returns abc\ def\ ghi
# if [ -f $AFILE ] # this test returns false every time with error [:too many arguments

if [ -f $TFILE ] # This test also returns FALSE with err [: too many arguments
then
  echo "Existing"
  # don't download
else
  echo "Not existing"
  # youtube-dl http://www.youtube.com/watch?v=AgkM5g_Ob-w
fi

【问题讨论】:

标签: linux bash shell


【解决方案1】:

始终引用您的文件名,使用%q 转义空格的想法是正确的,但是当与[ 运算符一起使用时,未加引号的$TFILE 被拆分为多个单词,导致-f 操作数当它实际上期望一个参数时收到太多参数。因此,一旦您将其双引号括起来,就会保留空格,并在条件中传递一个字面量的单个参数。

testFile="abc def ghi"
printf -v quotedFile '%q' "$testFile"

if [ -f "$quotedFile" ]; then
    printf 'My quoted file %s exists\n' "$quotedFile"
fi

以上内容应该适用于任何 POSIX 兼容的 shell([ 的用法)。但是,如果您仅针对 bash shell 的脚本,则可以使用 [[,其中永远不需要引用,因为它被评估为表达式。所以你可以这样做

file_with_spaces="abc def ghi"
if [[ -f $file_with_spaces ]]; then
    printf 'My quoted file %s exists\n' "$file_with_spaces"
fi

但一般来说,在bash 中为变量添加引号并没有什么坏处。你总是可以做到的。

【讨论】:

  • 很详细的解释,以后会引用Bash变量。由于目标平台是使用 Raspbian/Wheezy 的 Raspberry Pi,因此我仅限于 Bash,并且您的附加 Bash 示例可以完美运行。
  • 您的第一个 -f 示例无法运行,因为 "$quotedFile" 包含反斜杠,与文件名不同。 if [ -f "$testFile" ]; 可以正常工作,就像 [[ 的情况一样。并不是[[ 准确地“评估为表达式”;与[ 的区别在于它不会分词。 (引用man bash:“对[[]]之间的单词不进行分词和路径名扩展;进行波浪号扩展、参数和变量扩展、算术扩展、命令替换、进程替换和引号删除。 ")
  • (很抱歉在将近两年后才回复。一次杂乱的编辑将问题带回了我的列表,我在看到日期之前就回复了。)
猜你喜欢
  • 2023-03-05
  • 1970-01-01
  • 2018-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多