find コマンドを使用して見つかった各ファイルに対して Bash 機能を実行します。

find コマンドを使用して見つかった各ファイルに対して Bash 機能を実行します。

現在、各ファイル名を1行に正常に印刷するための次のコマンドがあります。

find . -exec echo {} \;

findコマンドが機能を実行するようにロジックを分割しようとしています。に基づいてこの問題私はこれを試しました:

my_function() {
    echo $1
}
export -f my_function
find . -exec bash -c 'my_function "$@"' bash {} +

すると、次のような結果が出力されます。

.

私も次の$@ように置き換えようとしましたが、$*その結果、$1すべてのファイルに改行文字がありませんでした。各ファイルを確認するロジックを実行したいので、$1一度に1つのファイルだけを確認したいと思います。出力をスペースに分割しようとしましたが、for file in $1ファイル名にスペースが含まれているファイルでは機能しません。コマンドで見つかったすべてのファイルに対してBash機能を実行するにはfind

編集:これは私が使用する完全なスクリプトです。とてもうまくいくようです。

# Ensures that non-csproj text files are formatted with LF line endings.
format() {
    for pathname do
        if [[ $pathname == *"git"* ]]; then
            continue
        elif [[ $pathname == *"csproj"* ]]; then
            continue
        fi
        dos2unix $pathname
    done
}
export -f format
find . -exec bash -c 'format "$@"' bash {} \;

ベストアンサー1

現在のディレクトリの内外のすべての一般ファイルで実行するには、名前dos2unix --newlineに文字列を含むファイルを避けてくださいgit

find . -type f ! -name '*git*' -exec dos2unix --newline {} +

つまり、名前がパターンと一致しないすべての一般ファイルを見つけ、*git*できるだけdos2unix --newline大きなバッチですべて一度に実行します。パス名にこの文字列を含むファイル(ディレクトリ内のファイルなど)を防ぐ! -name '*git*'には、変更してください。! -path '*git*'git.git

ディレクトリを明示的に防ぐが、名前に含めることができる他の.gitエントリを含めるには、次の手順を実行します。git

find . -name .git -prune -o -type f -exec dos2unix --newline {} +

検索ツリーでそのパス削除を使用して呼び出されたfindディレクトリが入力されても、フォームは停止します。.git-prune


質問を編集する前に答えてください。

あなたの関数は最初の引数だけを印刷します。 Dotはで使用される最上位の検索パスですfind。ディレクトリエントリに対して特定のフィルタリングを実行していないため、通過します(-type f一般ファイル、-nameまたは他の種類のfindテストのみ)。

関数に各引数を印刷させるには、次のようにします。

my_function() {
    printf '%s\n' "$@"
}

printf間に改行を使用して各パラメータを印刷してみましょう。

my_function() {
    for pathname do
        printf '%s\n' "$pathname"
    done
}

パラメータを繰り返して、printf各パラメータに対して1回呼び出します。

次の関数を呼び出すと正常に機能すると予想されます。

my_function "$@"

インラインbash -cスクリプトから。"$@"個別に引用されたスクリプトに指定されたすべての引数に拡張されます。

別のアプローチは、ループをbash -cスクリプトに移動することです。

for pathname do
    my_function "$pathname"
done

それではそこにいます。

my_function () {
    printf '%s\n' "$1"
}

これにより、パス名ごとに関数を一度呼び出すなど、明示的に実行されます。

コマンドfindは次のとおりです。

find . -exec bash -c 'for pathname do my_function "$pathname"; done' bash {} +

またはおそらくもっと読みやすくなります。

find . -exec bash -c '
    for pathname do
        my_function "$pathname"
    done' bash {} +

ところで、これは関連

shopt -s globstar nullglob dotglob

for pathname in ./**/*; do
    my_function "$pathname"
done

しかし、.処理されません。これを使用すると、機能をエクスポートする必要はありませんmy_function

関数の内部にループがある場合(この回答の最初の2つのコードスニペットのように)、次のように短縮されます。

shopt -s globstar nullglob dotglob

my_function ./**/*

おすすめ記事