web-dev-qa-db-ja.com

xargsはbashエイリアスを認識しません

次のコマンドを実行しようとしています。

find . -iname '.#*' -print0 | xargs -0 -L 1 foobar

ここで、「foobar」は、私の.bashrcファイルで定義されているエイリアスまたは関数です(私の場合、これは1つのパラメーターを受け取る関数です)。どうやらxargsはこれらを実行できるものとして認識していません。これを改善する賢い方法はありますか?

59

インタラクティブシェルだけがエイリアスについて知っているので、xargsをフォークせずにエイリアスを実行してみませんか?

find . -iname '.#*' -print0 | while read -r -d '' i; do foobar "$i"; done

ファイル名に改行が含まれていないことが確実な場合(ええと、なぜ改行するのでしょうか?)、これを次のように簡略化できます。

find . -iname '.#*' -print | while read -r i; do foobar "$i"; done

または、デフォルトのディレクトリはfind -iname '.#*' | ...であり、デフォルトのアクションは.であるため、-printだけでもかまいません。

もう1つの選択肢:

 IFS=$'\n'; for i in `find -iname '.#*'`; do foobar "$i"; done

単語は改行でのみ分割されることをBashに伝えます(デフォルト:IFS=$' \t\n')。ただし、これには注意する必要があります。一部のスクリプトは、変更された$IFSにうまく対応しません。

37
ephemient

Bashを使用すると、次のようにエイリアス(または関数)に渡される引数の数を指定することもできます。

alias myFuncOrAlias='echo'  # alias defined in your ~/.bashrc, ~/.profile, ...
echo arg1 arg2 | xargs -n 1 bash -cil 'myFuncOrAlias "$1"' arg0
echo arg1 arg2 | xargs  bash -cil 'myFuncOrAlias "$@"' arg0
11
tilo

xargsは、パラメータとして指定されたprogramexecできることを期待しているため、これは機能しません。

あなたの場合のfoobarは単なるbashエイリアスまたは関数であるため、実行するプログラムはありません。

bashによって返されるファイルごとにfindを開始する必要がありますが、次のように小さなシェルスクリプトを記述できます。

#!/bin/bash
. $(HOME)/.bashrc
func $*

次に、そのスクリプトの名前をパラメーターとしてxargsに渡します。

5
Alnitak

私は通常次のようなfindを使用します:

find . -iname '' -exec cmd '{}' \;

'{}'はファイル名に置き換えられ、\;実行チェーンを終了するために必要です。ただし、それが関数で機能しない場合は、bashを介して実行する必要がある場合があります。

find .. |sed -e "s/.*/cmd '&'/"|bash

Findは各ファイルを1行に出力し、sedはこれにコマンドのプレフィックスを付けて、bashにパイプして実行します。最初に| bashをスキップして、何が起こるかを確認してください。

1
Staale

試してみてください

find . -iname '.#*' -print0 | xargs -0 -L 1 $(foobar)
0
Jacob Adamczyk