bash 检查文件名是否存在包含空格的文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/47788046/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 16:40:52  来源:igfitidea点击:

Check if a file exists with a filename containing spaces

linuxbashshell

提问by casperl

I am testing in Bash for if a file is existing, where the file name is escaped using $(printf '%q' "$FNAME").

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

This always produces an error using if [ -f $FNAME ]as in the commented example below. How can I test for a filename that contains spaces and other characters?

这总是会产生错误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

回答by Inian

Always quote your file-name, the idea of using %qfor escaping the spaces is right, but when used with the [operator the unquoted $TFILEis split into multiple words causing the -foperand to receive too many arguments when it was actually expecting a single argument. So once you double-quote it, the white-spaces are preserved and a literal single argument is passed in the conditional.

始终引用您的文件名,%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

the above should apply well (the usage of [) in any POSIX compatible shells. But if you are targeting scripts for bashshell alone, you can use the [[in which quoting is never necessary as it evaluated as an expression. So you can just do

以上应该适用[于任何 POSIX 兼容的 shell (使用)。但是,如果您仅针对bashshell定位脚本,则可以使用[[其中的引用,因为它被视为表达式。所以你可以做

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

But in general it doesn't hurt to add quotes to variables in bash. You can always do it.

但总的来说,在bash. 你总是可以做到的。