3

私は bash スクリプトの初心者で、次のスクリプトに問題があります。

stdin から与えられたすべての引数を処理したい。次に、これらの引数が通常のテキスト ファイルであるかどうかを確認します。はいの場合、それらを配列に格納し、後で配列全体を処理したいと考えています。しかし、エラーが発生しています: files+=("$@")の行で単語 unexpexted を この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
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

ここに私がコーディングしたばかりのスクリプトがあり、あなたが求めることを行うようです... 3番目のテストの .. を必要なものに置き換えてください。残念ながら、私は上記の方法で配列を使用したことがないので、自分のやり方で書きました。お役に立てば幸いです。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

スプートニクの答えは非常に良い解決策です。独自の実装に固執したい場合に備えて、次の行を必ず修正してください。

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 に答える