
locate
「人が読める形式」(つまり、先行スペースなし)でパスリストを生成するコマンド出力など、コマンド出力を使用するときに出力を別のコマンド\
にリダイレクトするにはどうすればよいですか。
の出力は$ locate [something]
スペースを含むパスを生成するため、他のプログラムはスペースを含むパスを使用できません。たとえば、
$ du -h `locate *.doc`
これにより、スペースを含むすべてのファイルとディレクトリにエラーが発生します。 (空白でチックを包むことは機能しません)
答え1
それを使用する具体的な理由は何ですかlocate
?これはあなたの要件を満たすようです。
find . -type f -name '*doc' -exec du -h "{}" \;
つまり、本物locate
あるいは、同じツールを使用してその入力を別のプログラムに引数として渡したい場合は、一部のツールが提供する別々の出力と入力を find
利用できます。そして、両方とも読み取り用に設計されたよりプログラム的に使いやすい出力を得るためのオプション( 'sと's )があります。NUL
locate
find
locate
-0
find
-print0
xargs
それ -0
ディスカッション:
find . -type f -name '*doc' -print0 | xargs -0 du -h
locate -0 '*doc' | xargs -0 du -h
答え2
同じ行を複数のコマンドに渡したい場合、または渡す必要がある場合は、次のものを使用できます。
#!/usr/bin/env bash
T="${IFS}" # Save off the Internal Field Separator
IFS=$'\n' # Set it to newline.
while read file_line
do
echo "--"
echo "${file_line}"
echo "--"
done <<< $(locate $1)
IFS="${T} # Set it back to the original IFS.
仕上げておくのもいいと思います。どの""にスペースがある可能性がある変数です。
答え3
引用符のないコマンドの置き換え($(...)
または`...`
古代の形式)は、Bourneなどのシェル(zshでのみ分割)でSplit + globを呼び出します。
デフォルトでは、分割は$IFS
スペース、タブ、および改行(zshではNUL)の特殊パラメータを含む文字に対して行われます。これは、空白文字を含むファイル名でコマンドが機能しない理由を説明します。
次のことができます。
(IFS='
' # split on newline only
set -o noglob # disable glob
du -hc -- $(locate '*.doc'))
ただし、ファイル名に改行文字が含まれている場合はまだ失敗します。出力はlocate
まったく後処理できません。
ほとんどの実装にはファイルパスを区別して出力するオプションがlocate
あります。 NULは、ファイルパスには現れない唯一のバイト値です。つまり、出力が後処理可能であることを意味します。 NULに分割するだけです。-0
NUL
存在するzsh
:
IFS=$'\0'
du -hc -- $(locate -0 '*.doc')
あるいは、より良い方法は、明示的なNUL分割演算子を使用することです。
du -hc -- ${(0)"$(locate -0 '*.doc')"}
4.4+ では、bash
次のようになります。
readarray -td '' files < <(locate -0 '*.doc')
du -hc -- "${files[@]}"
それでも2つの質問が残っています。
locate
ファイルが見つからない場合は、du -hc --
引数なしで実行されます。つまり、現在の作業ディレクトリのディスク使用量がわかります。- 一方、
locate
多くのファイルが見つかると、最終的にシステムコールの制限に達し、execve()
エラーが発生する可能性があります。引数のリストが長すぎます。間違い。
以下を行うと、これらの問題をすべて回避できます。
locate -0 '*.doc' | xargs -r0 du -hc --
(-r
そして-0
GNU実装の非標準拡張xargs
と同様に、-h
GNU実装の非標準拡張ですdu
。)
しかし、これは新しい問題を引き起こします。制限を解決するために複数回xargs
実行されますが、これはいくつかの行を取得し、複数回ハードリンクされたファイルのディスク使用量が複数回計算されることを意味します。du
execve()
total
ありがとうございます-r
。ファイルがないとdu
実行されません。しかし、これは1行も表示されないという意味でもあります。locate
0 total
最新バージョンのGNUを使用すると、次du
の方法でこれらの問題を解決できます。
locate -0 '*.doc' | du --files0-from=- -hc
今回はパラメータの代わりにパイプを介してファイルのリストを渡すため、パラメータのサイズに制限はありません。これはまた、リストを格納するために多くのメモリを割り当てる必要がなく、出力を開始するdu
とすぐにlocate
処理を開始できることを意味します。