bashは空でない限りファイルのリストを繰り返します。

bashは空でない限りファイルのリストを繰り返します。

私はこれが簡単だと思いました。しかし、わかると、私が予想したよりも複雑でした。

ディレクトリ内の特定の種類のすべてのファイルを繰り返したいので、次のように作成します。

#!/bin/bash

for fname in *.zip ; do
   echo current file is ${fname}
done

これは効果があります一致するファイルが1つ以上ある場合ディレクトリに。ただし、一致するファイルがない場合は、次の結果が表示されます。

current file is *.zip

次に、次のことを試してください。

#!/bin/bash

FILES=`ls *.zip`
for fname in "${FILES}" ; do
    echo current file is ${fname}
done

ファイルが存在しない場合、ループ本体は実行されませんが、lsでエラーが発生します。

ls: *.zip: No such file or directory

一致しないファイルをきれいに処理するためにループを作成するにはどうすればよいですか?

答え1

では、パターンと一致しないパターンがリテラル文字列として処理されるのではなく、「消える」オプションをbash設定できます。nullglob

shopt -s nullglob
for fname in *.zip ; do
   echo "current file is ${fname}"
done

POSIXシェルスクリプトでは、それが存在するかどうかをfname確認できます(また、[ -f ]/ fifo / devices ...ディレクトリなどの他の種類ではなく、通常のファイル(または一般ファイルへのシンボリックリンク)であることを確認してください):

for fname in *.zip; do
    [ -f "$fname" ] || continue
    printf '%s\n' "current file is $fname"
done

名前が任意のタイプで終わるすべての(非表示)ファイルを繰り返すには、に[ -f "$fname" ]置き換えます。[ -e "$fname" ] || [ -L "$fname ].zip

で終わる名前も考慮したい場合*.zip.*.zip .zip *.zip.zip

答え2

set ./*                               #set the arg array to glob results
${2+":"} [ -e "$1" ] &&               #if more than one result skip the stat "$1"
printf "current file is %s\n" "$@"    #print the whole array at once

###or###

${2+":"} [ -e "$1" ] &&               #same kind of test
for    fname                          #iterate singly on $fname var for array
do     printf "file is %s\n" "$fname" #print each $fname for each iteration
done                                  

ここでコメントで関数呼び出しに言及しました...

file_fn()
    if     [ -e "$1" ] ||               #check if first argument exists
           [ -L "$1" ]                  #or else if it is at least a broken link
    then   for  f                       #if so iterate on "$f"
           do : something w/ "$f"
           done
    else   command <"${1-/dev/null}"    #only fail w/ error if at least one arg
    fi

 file_fn *

答え3

検索の使用

export -f myshellfunc
find . -mindepth 1 -maxdepth 1 -type f -name '*.zip' -exec bash -c 'myshellfunc "$0"' {} \;

export -fこれを行うには、シェル機能をエクスポートする必要があります。これfindで実行すると、bashシェル機能が実行され、現在のディレクトリレベルにのみ保持されます。

答え4

変える:

FILES=`ls *.zip`

努力する:

FILES=`ls * | grep *.zip`

これにより、lsが失敗した場合(あなたの場合)、失敗した出力を特定して空の変数として返します。

current file is      <---Blank Here

「ファイルが見つかりません」を返すようにいくつかのロジックを追加できます。

#!/bin/bash

FILES=`ls * | grep *.zip`
if [[ $? == "0" ]]; then
    for fname in "$FILES" ; do
        echo current file is $fname
    done
else
    echo "No Files Found"
fi

これにより、前のコマンドが成功した場合(値0で終了)、現在のファイルが印刷され、それ以外の場合は「ファイルが見つかりません」が印刷されます。

関連情報