3

我是 bash 脚本的初学者,但在使用以下脚本时遇到了麻烦。

我想处理来自标准输入的所有给定参数。然后我检查这些参数是否是普通的文本文件。如果是,我想将它们存储到数组中,然后我想遍历整个数组。但是我收到一个错误: 文件+ =(“$@”)行上的单词未解释 我试图像这样写文件=(“$@”) 但随后我在行上收到以下错误:“( " 意外(期待“fi”)

如果您有任何建议,我将不胜感激。先感谢您。

for file in "${argv[@]}"; do
    if [ -d "$file" ] 
    then
        echo "Error: '"$file"' is directory!" > /dev/stderr
    continue
    fi  


    if [[! -f "$file"] || [! -r "$file"]] 
    then
        echo "Error: '"$file"'!" > /dev/stderr
    continue
    fi  

    file "$file" | grep text >& /dev/null

    if [ ! $status ]
    then
    files+=("$@") 
    else
    echo "Error: '"$file"' not a text file!" > /dev/stderr
    fi
done

for file in "${files[@]}"; do
# .....
done
4

3 回答 3

1

尝试这样做:

#!/bin/bash

files=( )

for file; do
    if ([[ -f "$file && -r "$file" ]] && file "$file" | grep -q -i "text"); then
        files+=( "$file" )
    fi
done

for f in ${files[@]}; do
    # something with "$f"
done

另一个版本,带有错误处理:

#!/bin/bash

files=( )

for file; do
    if [[ ! -f "$file ]]; then
        echo >&2 "$file is not a regular file"
        continue
    fi

    if [[ ! -r "$file ]]; then
        echo >&2 "$file is not readable for $USER"
        continue
    fi

    if ! file "$file" | grep -q -i "text"; then
        echo >&2 "$file is not a text file"
        continue
    fi

    files+=( "$file" )
done

for f in ${files[@]}; do
    # something with "$f"
done

笔记

  • argv字面上不存在bashfor file就足够了
  • 而不是使用不存在的变量$status,而是使用预定义的变量$?
  • 不需要测试最后状态,你可以做一些更短的事情,比如grep -q pattern file && do_something
  • echo >&2意味着重定向到STDERR
于 2012-11-16T10:56:11.407 回答
0

这是我刚刚编写的脚本,似乎可以按照您的要求进行操作...只需将第三个测试中的 .. 替换为您需要的任何内容。不幸的是,我从来没有像你上面那样使用数组,所以我只是按照我的方式编写。我希望它有所帮助。只需将其作为 bash {scriptname}.sh 运行即可。任何进入标准的东西都会被处理。

#!/bin/bash

checkfile()
{

for i in $token
    do  

        if [ -f "${i}" ]; then
            {
            echo "It's a file"
            }   
        elif [ -d "${i}" ]; then
            {
            echo "It's a directory"
            }       
        elif [ -z "${i}" ]; then
            {
                :
            }
        fi

    done


}

while ( : )
do
    read token
    checkfile
    sleep 2
done

这是 bash 中的调试输出:

+ read token
a
+ checkfile
+ for i in '$token'
+ '[' -f a ']'
+ '[' -d a ']'
+ echo 'It'\''s a directory'
It's a directory
+ sleep 2
+ :
+ read token
b
+ checkfile
+ for i in '$token'
+ '[' -f b ']'
+ echo 'It'\''s a file'
It's a file
+ sleep 2
+ :
+ read token
a
+ checkfile
+ for i in '$token'
+ '[' -f a ']'
+ '[' -d a ']'
+ echo 'It'\''s a directory'
It's a directory
+ sleep 2
+ :
+ read token
于 2012-12-28T05:53:09.970 回答
0

Sputnick 的回答是一个很好的解决方案。万一您想坚持自己的实现,请确保更正以下行:

if [[! -f "$file"] || [! -r "$file"]] 

您应该始终在括号和测试表达式之间留有空格:[[ ! -f "$file" ]]. 此外,由于您使用的是||运算符,请使用双括号而不是单括号:

if [[ ! -f "$file" ]] || [[ ! -r "$file" ]] 

将行更改files+=("$@")files+=( "$file" )files[${#files[@]}]="$file"

不确定你想用你的status变量做什么。对于未分配的、已分配的变量 like或 any ,测试[ ! $status ]将返回 True 。如果要针对命令的退出状态进行测试,请使用整数测试而不是字符串比较:或.statusstatus=status=$(command >& /dev/null)file ...if [ $? -eq 0 ]if (($? == 0))

于 2013-01-05T07:52:01.997 回答