我正在编写一个基于菜单的 bash 脚本,菜单选项之一是发送带有文本文件附件的电子邮件。我无法检查我的文件是否是文本文件。这是我所拥有的:
fileExists=10
until [ $fileExists -eq 9 ]
do
echo "Please enter the name of the file you want to attach: "
read attachment
isFile=$(file $attachment | cut -d\ -f2)
if [[ $isFile = "ASCII" ]]
then
fileExists=0
else
echo "$attachment is not a text file, please use a different file"
fi
done
我不断收到错误cut:分隔符必须是单个字符。
答案1
file $attachment
从它说而不是 的事实来看file "$attachment"
,我猜你的脚本无法处理包含空格的文件名。但是,请注意,文件名可以包含空格,并且编写良好的脚本可以处理它们。那么请注意:$ file "foo bar" foo bar: ASCII text $ file "foo bar" | cut -d' ' -f2 bar:
一种流行且强烈推荐的方法是以空终止文件名:
$ file -0 "foo bar" | cut -d $'\0' -f2 : ASCII text
该
file
命令对文件的文件类型进行有根据的猜测。当然,猜测有时是错误的。例如,file
有时会查看一个普通的文本文件并猜测它是一个 shell 脚本、C 程序或其他东西。所以你不想检查输出是否file
是ASCII text
,你想看看是否说该文件是一个文本文件。如果您查看 的手册页file
,您会发现如果文件是文本文件,它或多或少承诺text
在其输出中包含该单词,但这可能是在像shell commands text
.因此,最好检查 的输出是否file
包含单词text
:isFile=$(file -0 "$attachment" | cut -d $'\0' -f2) case "$isFile" in (*text*) echo "$attachment is a text file" ;; (*) echo "$attachment is not a text file, please use a different file" ;; esac
答案2
case $(file -b --mime-type - < "$attachment") in
(text/*)
printf '%s\n' "$attachment is probably text according to file"
case $(file -b --mime-encoding - < "$attachment") in
(us-ascii) echo "and probably in ASCII encoding"
esac
esac
答案3
问题发生在cut -d\ -f2
.将其更改为cut -d\ -f2
.
对于cut
,参数如下所示:
# bash: args(){ for i; do printf '%q \\\n' "$i"; done; }
# args cut -d\ -f2
cut \
-d\ -f2 \
问题就在这里。\
将空格转义为空格文字,而不是 shell 中参数之间的分隔符,并且您没有添加额外的空格,因此整个-d\ -f2
部分显示为一个参数。您应该添加一个额外的空格 so-d\
并-f2
显示为两个参数。
为了避免混淆,许多人使用引号来-d' '
代替。
PS:我宁愿使用而不是使用文件并将所有内容都设置为 ASCII
if file "$attachment2" | grep -q text$; then
# is text
else
# file doesn't think it's text
fi
答案4
另一种选择是不使用正cut
则表达式并将其与以下完整输出进行匹配file
:
#...
isFile=$(file $attachment)
if [[ "$var" =~ ^[^:]*:\ ASCII ]]
#...