Bash:如何处理所有给定的参数并将它们存储到数组中

时间:2012-11-16 10:47:37

标签: bash arguments

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

我想从stdin处理所有给定的参数。然后我检查,如果这些参数是普通的文本文件。如果是的话,我想将它们存储到数组中,之后我想要遍历整个数组。 但是我收到了一个错误:单词expexted 在文件+ =(“$ @”)的行上 我试着像这样写 files =(“$ @”) 但后来我在线上得到了以下错误:“(”意外(期待“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

3 个答案:

答案 0 :(得分: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

答案 1 :(得分: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

答案 2 :(得分:0)

Sputnick's answer是一个非常好的解决方案。如果您想坚持自己的实现,请确保更正以下行:

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

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

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

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

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