命令在 CLI 中有效,但在 bash 中无效
command works in CLI but not in bash
在 bash 中做一个简单的阅读:
list.txt的内容:
/foo/bar/mydirectory/myfile.jpg
/foo/bar/mydirectory/deletedfile.jpg
/foo/bar/pictures\of\coffee\cups/coffee-cup-42.jpg
#!/bin/bash
file="/foo/bar/list.txt"
while read -r line; do
echo "VALUE OF LINE VARIABLE IS: $line"
echo "COMMAND LINE IS: find -f $line"
find -f $line
# either file found, or "no such file" error
done <$file
脚本输出:
dumbjoe$ ./read-test.sh
行变量的值是:/foo/bar/mydirectory/myfile.jpg
命令行是:find -f [=62= .jpg
/foo/bar/mydirectory/myfile.jpg 找到文件
行变量的值是:/foo/bar/mydirectory/deletedfile.jpg
命令行是:find -f /foo/bar/mydirectory/deletedfile.jpg
find:/foo/bar/mydirectory/deletedfile.jpg:没有那个文件或目录 找不到文件
行变量的值是:/foo/bar/pictures\ of\ coffee\ cups/coffee-cup-42.jpg
命令行是:find -f /foo/bar/pictures\ of \ coffee\ cups/coffee-cup-42.jpg
find: /foo/bar/pictures\: 否这样的文件或目录
find: of\: 没有这样的文件或目录
find: coffee\: 没有这样的文件或目录
find: cups/coffee-cup-42.jpg: 没有这样的文件或目录 WHAT???
运行终端中的命令
dumbjoe$ find -f /foo/bar/pictures\of\coffee\cups/coffee-cup-42.jpg
/foo/bar/pictures\ of\ coffee\ cups/coffee-cup-42.jpg 找到文件
为什么这在脚本中不起作用??
编辑:最终我所追求的是下面,我迷路的地方是变量“多转义”:
file=$LISTOFFILES
while IFS= read -r line
do
let "FILESTESTED+=1"
FOUND="$(find -f $line)"
# if file is not found, ignore the error
exec 2> /dev/null
# if file is found:
if [ "$FOUND" == "$line" ]
then
echo "FOUND: $line" >> $REPORT
FILESIZE="$(find $line -exec ls -l {} \; | awk '{ print }')"
echo "SIZE is: $FILESIZE" >> $REPORT
echo "-----------------------------------" >> $REPORT
let "SPACETOTAL= SPACETOTAL + FILESIZE"
let "FILES_FOUND_COUNT+=1"
fi
done <$file
如果路径中没有空格,所有这些都有效。
看起来像是一个转义问题,可以试试 find -f '$line'
同时更改您的#!到 #!/bin/bash -x 你会得到一堆有用的调试信息。
您不需要转义输入文件中的空格,因为 shell 不会处理它们。直接引用参数展开即可。
将以下内容放入 list.txt
:
/foo/bar/mydirectory/myfile.jpg
/foo/bar/mydirectory/deletedfile.jpg
/foo/bar/pictures of coffee/coffee-cup-42.jpg
然后将脚本更改为
#!/bin/bash
file="/foo/bar/list.txt"
while IFS= read -r line; do
echo "VALUE OF LINE VARIABLE IS: $line"
echo "COMMAND LINE IS: find -f $line"
find -f "$line"
# either file found, or "no such file" error
done < "$file"
实际文件路径是 /foo/bar/pictures of coffee cups/coffee-cup-42.jpg
(没有反斜杠)。
这个:
find -f /foo/bar/pictures\ of\ coffee\ cups/coffee-cup-42.jpg
相当于:
find -f '/foo/bar/pictures of coffee cups/coffee-cup-42.jpg'
有效。 (反斜杠只是一种引用机制,类似于单引号或双引号。)
相比之下,这个:
variable='/foo/bar/pictures\ of\ coffee\ cups/coffee-cup-42.jpg'
find -f $variable
相当于:
variable='/foo/bar/pictures\ of\ coffee\ cups/coffee-cup-42.jpg'
find -f '/foo/bar/pictures\' 'of\' 'coffee\' 'cups/coffee-cup-42.jpg'
向 find
发送了太多单独的参数,其中一些参数末尾有虚假的反斜杠;所以命令不起作用。
主要问题是反斜杠是您键入 Bash 命令时的一个特征。它们在脚本中的工作方式与您在 shell 中键入时的效果一样好,但它们仅在实际位于命令本身中时才有效,而不仅仅是在您传递给命令的变量中。
第二个问题是 Bash 有一个奇怪的功能,称为“分词”,如果您的变量包含 whitespace 并且您没有用双引号引起来,它找到 space 并将其拆分为单独的参数。恕我直言,这是一个糟糕的功能,但它是由 POSIX 指定的,我不希望它永远改变。幸运的是,有一个简单的解决方法,即:总是 用双引号括起变量扩展。
所以,要解决这个问题:
- 修改您的文件以删除不属于实际文件路径的虚假反斜杠。
- 写
find -f "$line"
而不是 find -f $line
。
在 bash 中做一个简单的阅读:
list.txt的内容:
/foo/bar/mydirectory/myfile.jpg
/foo/bar/mydirectory/deletedfile.jpg
/foo/bar/pictures\of\coffee\cups/coffee-cup-42.jpg
#!/bin/bash
file="/foo/bar/list.txt"
while read -r line; do
echo "VALUE OF LINE VARIABLE IS: $line"
echo "COMMAND LINE IS: find -f $line"
find -f $line
# either file found, or "no such file" error
done <$file
脚本输出:
dumbjoe$ ./read-test.sh
行变量的值是:/foo/bar/mydirectory/myfile.jpg
命令行是:find -f [=62= .jpg
/foo/bar/mydirectory/myfile.jpg 找到文件
行变量的值是:/foo/bar/mydirectory/deletedfile.jpg
命令行是:find -f /foo/bar/mydirectory/deletedfile.jpg
find:/foo/bar/mydirectory/deletedfile.jpg:没有那个文件或目录 找不到文件
行变量的值是:/foo/bar/pictures\ of\ coffee\ cups/coffee-cup-42.jpg
命令行是:find -f /foo/bar/pictures\ of \ coffee\ cups/coffee-cup-42.jpg
find: /foo/bar/pictures\: 否这样的文件或目录
find: of\: 没有这样的文件或目录
find: coffee\: 没有这样的文件或目录
find: cups/coffee-cup-42.jpg: 没有这样的文件或目录 WHAT???
运行终端中的命令
dumbjoe$ find -f /foo/bar/pictures\of\coffee\cups/coffee-cup-42.jpg
/foo/bar/pictures\ of\ coffee\ cups/coffee-cup-42.jpg 找到文件
为什么这在脚本中不起作用??
编辑:最终我所追求的是下面,我迷路的地方是变量“多转义”:
file=$LISTOFFILES
while IFS= read -r line
do
let "FILESTESTED+=1"
FOUND="$(find -f $line)"
# if file is not found, ignore the error
exec 2> /dev/null
# if file is found:
if [ "$FOUND" == "$line" ]
then
echo "FOUND: $line" >> $REPORT
FILESIZE="$(find $line -exec ls -l {} \; | awk '{ print }')"
echo "SIZE is: $FILESIZE" >> $REPORT
echo "-----------------------------------" >> $REPORT
let "SPACETOTAL= SPACETOTAL + FILESIZE"
let "FILES_FOUND_COUNT+=1"
fi
done <$file
如果路径中没有空格,所有这些都有效。
看起来像是一个转义问题,可以试试 find -f '$line'
同时更改您的#!到 #!/bin/bash -x 你会得到一堆有用的调试信息。
您不需要转义输入文件中的空格,因为 shell 不会处理它们。直接引用参数展开即可。
将以下内容放入 list.txt
:
/foo/bar/mydirectory/myfile.jpg
/foo/bar/mydirectory/deletedfile.jpg
/foo/bar/pictures of coffee/coffee-cup-42.jpg
然后将脚本更改为
#!/bin/bash
file="/foo/bar/list.txt"
while IFS= read -r line; do
echo "VALUE OF LINE VARIABLE IS: $line"
echo "COMMAND LINE IS: find -f $line"
find -f "$line"
# either file found, or "no such file" error
done < "$file"
实际文件路径是 /foo/bar/pictures of coffee cups/coffee-cup-42.jpg
(没有反斜杠)。
这个:
find -f /foo/bar/pictures\ of\ coffee\ cups/coffee-cup-42.jpg
相当于:
find -f '/foo/bar/pictures of coffee cups/coffee-cup-42.jpg'
有效。 (反斜杠只是一种引用机制,类似于单引号或双引号。)
相比之下,这个:
variable='/foo/bar/pictures\ of\ coffee\ cups/coffee-cup-42.jpg'
find -f $variable
相当于:
variable='/foo/bar/pictures\ of\ coffee\ cups/coffee-cup-42.jpg'
find -f '/foo/bar/pictures\' 'of\' 'coffee\' 'cups/coffee-cup-42.jpg'
向 find
发送了太多单独的参数,其中一些参数末尾有虚假的反斜杠;所以命令不起作用。
主要问题是反斜杠是您键入 Bash 命令时的一个特征。它们在脚本中的工作方式与您在 shell 中键入时的效果一样好,但它们仅在实际位于命令本身中时才有效,而不仅仅是在您传递给命令的变量中。
第二个问题是 Bash 有一个奇怪的功能,称为“分词”,如果您的变量包含 whitespace 并且您没有用双引号引起来,它找到 space 并将其拆分为单独的参数。恕我直言,这是一个糟糕的功能,但它是由 POSIX 指定的,我不希望它永远改变。幸运的是,有一个简单的解决方法,即:总是 用双引号括起变量扩展。
所以,要解决这个问题:
- 修改您的文件以删除不属于实际文件路径的虚假反斜杠。
- 写
find -f "$line"
而不是find -f $line
。