如何在 bash 脚本中检查文件名的扩展名?
Posted
技术标签:
【中文标题】如何在 bash 脚本中检查文件名的扩展名?【英文标题】:How to check the extension of a filename in a bash script? 【发布时间】:2010-09-29 06:17:26 【问题描述】:我正在用 bash 编写一个夜间构建脚本。 一切都很好,除了一点点障碍:
#!/bin/bash
for file in "$PATH_TO_SOMEWHERE"; do
if [ -d $file ]
then
# do something directory-ish
else
if [ "$file" == "*.txt" ] # this is the snag
then
# do something txt-ish
fi
fi
done;
我的问题是确定文件扩展名,然后采取相应措施。我知道问题出在 if 语句中,测试 txt 文件。
如何确定文件是否有 .txt 后缀?
【问题讨论】:
如果您的文件名中有空格,这将中断。 除了Paul的回答,你可以使用$(dirname $PATH_TO_SOMEWHERE)
和$(basename $PATH_TO_SOMEWHERE)
来拆分文件夹和目录,做一些directory-ish和file-ish
【参考方案1】:
制作
if [ "$file" == "*.txt" ]
像这样:
if [[ $file == *.txt ]]
即双括号,不加引号。
==
的右侧是一个 shell 模式。
如果您需要正则表达式,请使用=~
。
【讨论】:
我不知道这个。 == 或 != 的右侧扩展为 shell 模式似乎是一种特殊情况。我个人认为这比我的答案更清楚。 我是 bash 新手,我花了一些时间才弄清楚如何在多条件if
语句中使用它。我在这里分享它以防它帮助某人。 if [[ ( $file == *.csv ) || ( $file == *.png ) ]]
@cheflo 通常适用于多种情况。在这种特定情况下,您还可以使用if [[ $file =~ .*\.(csv|png) ]]
。它更短、更清晰、更容易添加额外的扩展,并且可以很容易地进行配置(通过将“csv|png”放入变量中)。
您可以在文件两边加上双引号。 if [[ "$file" == *.txt ]]
如果文件名中有空格,则需要双引号。
我应该使用这个答案而不是接受的答案吗?【参考方案2】:
我想你想说“$file 的最后四个字符是否等于.txt
?”如果是这样,您可以使用以下内容:
if [ "$file: -4" == ".txt" ]
请注意,file:
和 -4
之间的空格是必需的,因为 ':-' 修饰符的含义不同。
【讨论】:
为此,您也可以在 Windows 机器上将 command.com 重命名为 command.txt。 如果要指定不等式,请记住包含额外的括号:if [[ $file: -4 != ".txt" ]] @RamRajamony 为什么在测试不等式时必须使用 [[? 在 bash 中,除非您在第一个变量周围加上引号,否则这将产生“[: ==: unary operator expected”错误。所以改为if [ "$file: -4" == ".txt" ]
。
对于那些可能不熟悉 bash/shell 语法的人的注意事项:-4 之前的空格很重要。 "$file:-4" == ".txt"
(没有空格)将无法按预期工作。【参考方案3】:
在 Unix 系统上,您无法确定 .txt 文件确实是文本文件。你最好的选择是使用“文件”。也许尝试使用:
file -ib "$file"
然后您可以使用 MIME 类型列表来匹配或解析 MIME 的第一部分,您可以在其中获取“文本”、“应用程序”等内容。
【讨论】:
由于file -i...
包含mime编码,可以使用file --mime-type -b ...
【参考方案4】:
你也可以这样做:
if [ "$FILE##*." = "txt" ]; then
# operation for txt files here
fi
【讨论】:
case $FILE in *.txt ) ... ;; esac
看起来更健壮和惯用。
这将适用于最基本的shell,更通用。
最便携的答案。【参考方案5】:
如果您确实想查找有关文件的信息而不是依赖扩展名,则可以使用“文件”命令。
如果您对使用该扩展感到满意,您可以使用 grep 来查看它是否匹配。
【讨论】:
是的,我知道file
命令。我实际上已经尝试根据所述命令的输出进行匹配......但我在这些 if 语句中失败了。【参考方案6】:
关于如何在linux中获取文件名中可用的扩展名的正确答案是:
$filename##*\.
打印目录中所有文件扩展名的示例
for fname in $(find . -maxdepth 1 -type f) # only regular file in the current dir
do echo $fname##*\. #print extensions
done
【讨论】:
您的答案使用双反斜杠,但您的示例仅使用单个反斜杠。你的例子是正确的,你的答案不是。【参考方案7】:类似于“文件”,使用稍微简单一点的“mimetype -b”,无论文件扩展名如何,都可以使用。
if [ $(mimetype -b "$MyFile") == "text/plain" ]
then
echo "this is a text file"
fi
编辑:如果 mimetype 不可用,您可能需要在系统上安装 libfile-mimeinfo-perl
【讨论】:
您应该明确指出,“mimetype”脚本并非在所有系统上都可用。 完成,添加 libfile-mimeinfo-perl【参考方案8】:我编写了一个 bash 脚本,它查看文件的类型,然后将其复制到一个位置,我用它来查看我从我的 Firefox 缓存中在线观看的视频:
#!/bin/bash
# flvcache script
CACHE=~/.mozilla/firefox/xxxxxxxx.default/Cache
OUTPUTDIR=~/Videos/flvs
MINFILESIZE=2M
for f in `find $CACHE -size +$MINFILESIZE`
do
a=$(file $f | cut -f2 -d ' ')
o=$(basename $f)
if [ "$a" = "Macromedia" ]
then
cp "$f" "$OUTPUTDIR/$o"
fi
done
nautilus "$OUTPUTDIR"&
它使用了与此处介绍的类似的想法,希望这对某人有所帮助。
【讨论】:
【参考方案9】:我猜'$PATH_TO_SOMEWHERE'
类似于'<directory>/*'
。
在这种情况下,我会将代码更改为:
find <directory> -maxdepth 1 -type d -exec ... \;
find <directory> -maxdepth 1 -type f -name "*.txt" -exec ... \;
如果你想对目录和文本文件名做一些更复杂的事情,你可以:
find <directory> -maxdepth 1 -type d | while read dir; do echo $dir; ...; done
find <directory> -maxdepth 1 -type f -name "*.txt" | while read txtfile; do echo $txtfile; ...; done
如果您的文件名中有空格,您可以:
find <directory> -maxdepth 1 -type d | xargs ...
find <directory> -maxdepth 1 -type f -name "*.txt" | xargs ...
【讨论】:
这些是您如何在 shell 中执行“循环”的绝佳示例。显式for
和 while
循环最好保留用于需要更复杂的循环体。以上是关于如何在 bash 脚本中检查文件名的扩展名?的主要内容,如果未能解决你的问题,请参考以下文章
错误 - 在Windows 7中使用“Git Bash Here”时,“文件扩展名.vbs没有脚本引擎”