ファイルのUUIDを生成しようとしているコマンドがあります。
_find -printf "%P\n"|sort|xargs -L 1 echo $(uuid)
_
しかし、結果として、xargs
は$(uuid)
サブシェルを1回だけ実行します。
_8aa9e7cc-d3b2-11e4-83a6-1ff1acc22a7e file1
8aa9e7cc-d3b2-11e4-83a6-1ff1acc22a7e file2
8aa9e7cc-d3b2-11e4-83a6-1ff1acc22a7e file3
_
xargs
を取得して各入力でサブシェルコマンドを実行するためのワンライナー(つまり関数ではない)はありますか?
これは、$(uuid)
が現在のシェルで展開されるためです。シェルを明示的に呼び出すことができます。
find -printf "%P\n"| sort | xargs -I '{}' bash -c 'echo $(uuid) {}'
ところで、私は次のコマンドを使用します:
find -exec bash -c 'echo "$(uuid) ${1#./}"' -- '{}' \;
xargs
なし。
Forループの場合:
for i in $(find -printf "%P\n" | sort) ; do echo "$(uuid) $i"; done
編集:これを行う別の方法:
find -printf "%P\0" -exec uuid -v 4 \; | sort | awk -F'\0' '{ print $2 " " $1}'
これにより、ファイル名の後に、ソートを実行させるためのuuid(サブシェルは不要)が出力され、nullで区切られた2つの列が交換されます。
hek2mglの答え 問題をうまく説明し、彼の解決策はうまく機能します。この答えはパフォーマンスを見ています。
受け入れられた答えは、すべての入力行に対してbash
プロセスを作成するため、少し遅いです。
xargs
は一般にシェルコードループよりも速く、より望ましいですが、この特定のケースでは、各反復でシェル機能が必要になるため、役割が逆になります。
次の代替ソリューションは、while
ループを使用して入力行を処理します。私のマシンでは、xargs
の約2倍の速度です。解決。
find . -printf "%P\n" | sort | while IFS= read -r f; do echo "$(uuid) $f"; done
while
ではなくfor
を使用していることに注意してください。これは、for
がコマンド出力を確実に解析できないためです(つまり、空白が埋め込まれたファイル名はコマンドを壊してしまいます。 httpを参照) ://mywiki.wooledge.org/DontReadLinesWithFor )。改行が埋め込まれたファイル名(非常にまれ)が心配で、[〜#〜] gnu [〜#〜]ユーティリティを使用する場合は、NULバイトを区切り文字として使用できます。
find . -printf "%P\0" | sort -z | while IFS= read -d '' -r f; do echo "$(uuid) $f"; done
更新:最速アプローチは、シェルループをまったく使用しないことです。 ᴳᵁᴵᴰᴼの巧妙な答えによって証明されます。彼の答えのポータブルバージョンについては、以下を参照してください。
互換性に関する注意:
OPのfind
コマンドは、[〜#〜] gnu [〜#〜]find
(Linux)の使用を意味し、機能( -printf
)他のプラットフォームでは機能しない可能性があります。
これがポータブルバージョンの ᴳᵁᴵᴰᴼの答えで、find
(およびawk
)のPOSIX準拠の機能のみを使用しています。
ただし、uuid
はPOSIXユーティリティではないことに注意してください。 LinuxおよびBSDのようなシステム(OSXを含む)にはuuidgen
ユーティリティがあるため、コマンドは代わりにそれを使用します。
find . -exec printf '%s\t' {} \; -exec uuidgen \; |
awk -F '\t' '{ sub(/.+\//,"", $1); print $2, $1 }' | sort -k2