"find -exec"はスペースを含むファイル名をどのように渡しますか?

"find -exec"はスペースを含むファイル名をどのように渡しますか?

名前にスペースを含むいくつかのファイルを含むディレクトリがある場合

$ ls -1 dir1
file 1
file 2
file 3

次のように、すべてのエントリを別のディレクトリに正常にコピーできます。

$ find dir1 -mindepth 1 -exec cp -t dir2 {} +

ただし、の出力にはfind dir1 -mindepth 1エスケープされていないスペースが含まれています。

$ find dir1 mindepth 1
dir1/file 1
dir1/file 3
dir1/file 3

print0代わりに使用すると、print出力にまだエスケープされていないスペースが含まれます。

$ find dir1 mindepth 1 -print0
dir1/file 1dir1/file 2dir1/file 3

これらのファイルを手動でコピーするにはcpスペースをエスケープする必要がありますが、引数が出cpたときにコマンドの最後にまたはをfind使用すると不要なようです。+\;

その理由は何ですか?

答え1

コマンドはfindコマンドを直接実行します。このコマンド(filename引数を含む)は、シェルまたはファイル名を変更できる他の項目によって処理されません。とても安全です。

{}コマンドラインに表示されているファイル名をエスケープする必要はありませんfind

findディスクの元のファイル名をコマンドの内部パラメータのリスト(-execあなたの場合はcpコマンド)に直接渡します。

答え2

質問は2つの部分に分けられます。

  • どのようにする find-execファイル名にスペースが含まれている問題なくプログラムを呼び出すことができます。
  • このオプションの利点は何ですか-print0

1つ目findは、実際には、次の関連する呼び出しセットの1つであるシステム呼び出しを作成することです。「実現する」。ファイル名をこの呼び出しに直接引数として渡し、ファイル名に関する情報を失うことなく(新しいプロセスを作成した後)呼び出しに直接渡します。

POSIXfind特徴は+以下のように説明される。理由:

SVR4ユーティリティの特徴は基本的な+ターミネータfindです。-execこれにより、ファイル名の特殊文字(特に新しいチーム文字)は一緒にグループ化され、これらのファイル名がにパイプされている場合は発生しませんxargs。他の実装では、この問題を解決するための追加の方法が追加されています。特に、ファイル名を-print0作成するためにヌルバイトターミネータを使用する基本的な実装があります。これはここで考慮されたが、採用されていない。 NULLターミネータを使用することは、 -print0findの出力を処理するすべてのユーティリティが、現在読んでいるNULLターミネータを解析するための新しいオプションを追加する必要があることを意味します。

それ」特にPrimaryは、問題をさまざまな方法で解決するGNUを意味します。FreeBSDもこれをサポートします-print0findxargsfindそしてxargs。オプションを追加すると-0(注マニュアルページxargsを呼び出すと、プログラムは "ヌルバイト"文字で終わる行を受け入れます。順番にxargs呼び出される実装する- 実行する機能それ働く関数と関数の主な違い-print0は、前者はパイプを介してファイル名を渡し、後者はそうではないということです。開発者はほとんどすべての機能の用途を見つけることができます。パイプラインも例外ではありません。-0+

OPの例に戻り、次に-t見つからないオプションを使用します。cpPOSIX CP。代わりに提供される拡張です(「非標準機能」とも呼ばれます)。GNU CP-0拡張機能はxargsこの例を改善しませんが、他の状況で効果的に使用できます。+GNUがfind許可する移植可能な選択肢があることを覚えておいてください。

答え3

これは説明でなければなりませんが、大きすぎます。)

実験が好きな人のために:

渡された場所引数を一覧表示するスクリプトを作成し、名前をlist_positional_parameters.sh

#!/bin/bash

# http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_09_07.html
# Try globbing patterns, e.g. "X[[:digit:]][[:digit:]]" to see what happens

if [ $# -lt 1 ]; then
   echo "Usage: $0 and then at least one parameter"
   exit 1
fi

counter=1

while (($#)); do
   echo "$counter = '$1'"
   # pop positional argument 1 off the stack of positional arguments
   shift
   (( counter++ ))
done

$dirディレクトリから実行してくださいfind

find "$dir" -exec ./list_positional_parameters.sh '{}' ';' | less

予想どおり、名前にスペースがあるかどうかにかかわらず、すべての呼び出しにはファイル名という1つのパラメータしかありません。

関連情報