【问题标题】:shell script that determines file type确定文件类型的 shell 脚本
【发布时间】:2014-12-13 11:51:26
【问题描述】:

遇到这个问题,我可以寻求帮助....

创建一个 shell 脚本 fileType.sh,它接受一个命令行参数,一个文件路径(可能是相对的或绝对的)。脚本应检查该文件并打印由短语组成的单行

Windows ASCII

如果文件是带有 CR/LF 行终止符的 ASCII 文本文件,或者

其他的

如果文件是二进制文件或带有“Unix”LF 行终止符的 ASCII。

例如:

./fileType.sh ~cs252/Assignments/ftpAsst/d3.dat

Windows ASCII

./fileType.sh /bin/cat

其他的

./fileType.sh 文件类型.sh

其他的

./fileType.sh /usr/share/dict/words

其他的

当给定现有文件的合法路径时,您的脚本不应产生任何其他输出。 (如果给一个不存在的文件的路径不正确,它可能会产生任何你喜欢的东西。)

Unix 新手,我有一些 C++ 经验。

这就是我的脚本中的内容。

#!/bin/sh
grep -r 'Windows ASCII' $1
if $(file == "ASCII TEXT");then
echo Windows ASCII
else
echo Something Else 
fi

这是我的输出:

./fileType.sh: 4: ./fileType.sh: [文件:未找到

其他的

#!/bin/sh

grep -r "Windows ASCII" $1
if test "$( file "$1")" = ' ASCII text, with  CRFL line terminators'; then
echo Windows ASCII
else 
echo Something else
fi

当我传入的文件应该给出 Windows ASCII 的输出时,我现在的输出只是别的东西......

【问题讨论】:

标签: shell


【解决方案1】:

您的脚本正在尝试执行名为“[file”的命令。那不是你想要的。没有提供有关此解决方案的可取性的建议,但实现您似乎想要的语法是:

if test "$( file "$1" )" = 'ASCII TEXT'; then

if [ "$( file "$1" )" = 'ASCII TEXT' ]; then 

[ 是一个命令(shell 内置还是外部无关),它与命令test 完全相同,只是它希望它的最后一个参数是]。这是一个令人发指的组合,它试图使语法看起来好像括号是 shell 语言中的标记。 IMO,最好使用test,因为它清楚地表明它不是语法的一部分。

【讨论】:

  • 需要"$( file "$1" )" 才能正确处理带有空格、全局字符等的文件名。
  • 我编辑了我的脚本并处理了错误消息,但是我仍然没有得到预期的输出。当我应该得到“Windows ASCII”时,我得到了“别的东西”......
  • @Bryan 请注意,test ([ … ]) 中的比较区分大小写。尝试在您的终端中运行file 命令,然后使用您收到的消息。另请注意,file 只是一种猜测,可能会比您需要的更多 - 例如。 C 源代码将是 ASCII C program text
  • 我在终端中运行了文件命令,我正在测试的文件是“ASCII 文本,带有 CRLF 行终止符”,所以我调整了脚本以反映这一点,但是当我仍然得到“其他东西”时我应该得到“Windows ASCII”作为我的输出,我将发布更新的脚本......
  • 字符串“ASCII text, with CRLF line terminators”与字符串“ASCII TEXT”几乎不一样。
【解决方案2】:

实际实现需要您解释/测试file 返回的结果多一点。威廉的回答为您指明了那个方向。有点不清楚您是否需要传统 shell 编程的解决方案(如 Bourne Shell 中)或者您是否正在寻找 Bash(或等效)解决方案.上面,我想混乱围绕着使用:

if test "$( file "$1" )" = 'ASCII TEXT'; then

虽然这将为您确认文件是带有lf 分隔符的文本,不包括所有其他分隔符,但它并不能让您判断文件是否包含带有CRLF 行尾的行(只是它不是'ASCII TEXT')。要独占判断文件是否包含CRLF 行尾,需要测试file 输出找到CRLF

无论外壳如何,方法都是相同的。捕获file命令的结果,并测试结果是否包含CRLF。 shell 之间的区别在于你如何完成测试。以下示例提供了一种方法来测试 Bourne Shell 并在 Bash 中再次进行相同的测试(注意:有很多方法可以完成测试,这只是一种方法):

#!/bin/sh

line=`file -b "$1"`

## Bourne Shell
win=0
for i in $line; do                                # search for CRLF in $line
    if test `expr match "$i" "CRLF"` -gt 0 ; then
        win=1
        break
    fi
done

if test "$win" -eq 1 ; then 
    printf "Windows ASCII\n"
else
    printf "Something else\n"
fi

## BASH
if [[ "$line" =~ "CRLF" ]]; then                  # use substring operator
    printf "Windows ASCII\n"
else
    printf "Something else\n"
fi

/CRLF 示例:

$ ./Type.sh ../../utl/tst/config.win.ini
Windows ASCII
Windows ASCII

/LF 示例:

$ ./Type.sh ../../utl/tst/config.ini
Something else
Something else

【讨论】:

  • 我已经编辑了我的 shell 以反映上面的 Bourne 版本,但是我现在意识到我需要搜索两个字符串“ASCII”和“CRLF”。所以我一直在尝试调整测试线来搜索两个变量 if test expr match "$i" "CRFL" | expr match "$1" "ASCII" -g 0;然后.....我正在使用tcsh,基本上我正在尝试同时搜索两个变量。在 C++ 中,我会使用“&&”运算符。我不知道 unix 是否有这样的运算符,所以我试图将它们“管道”在一起......但没有运气。
  • 你应该可以使用if test $(expr match "$i" "CRLF") -gt 0 -o $(expr match "$i" "ASCII") -gt 0 ; then 如果不行,那么使用if test $(expr match "$i" "CRLF") -gt 0 ; then ...stuff... elif $(expr match "$i" "ASCII") -gt 0 ; then ...stuff... fi注意: 上面使用了$(),因为我不能在此评论中使用反引号。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-08
  • 2015-09-24
相关资源
最近更新 更多