変数でスペースを処理する方法

変数でスペースを処理する方法

私はいくつかのスクリプトを書いています。

for x in `find ./ -name *.pdf`
do
  echo pathname $x
done

私のファイル名はですTest1 ( Volume II)Test2 ( Volume II)

pathname Test1
pathname (
pathname Volume
pathname II

どのように変数として保持しますか?

ベストアンサー1

このサイトで何度も述べたように、Bourne / POSIXシェルの引用符なしの変数拡張(または)、または$varコマンドの置き換え(たとえば、またはほとんどのシェルの算術拡張(たとえば))は、分割+glob演算記号です。`cmd`$(cmd)$((11 * 11))

内容$varまたは出力(末尾の改行なし)は、特殊変数(デフォルトではSPC、TAB、およびNL文字(およびNUL)を含む)の現在の値と、その変数によって生成された各単語に基づいてcmd分割されます。ファイル名によって生成されます。$IFSzshワイルドカード

たとえば、find出力./foo bar.pdf\n./*foo*\tbar.pdf\n\tTABおよび\nNLを表す)がデフォルト値の場合、コマンド置換は(末尾の改行を削除)に展開され、次に、、およびに分割されます$IFS。ここで、ワイルドカードパターンは引数の数だけ拡張されます。現在のディレクトリにあるように、Exists名には。./foo bar.pdf\n./*foo*\tbar.pdf./foobar.pdf./*foo*foo.pdf./*foo*foo

改行文字にのみ分割するには、$IFS次のように改行文字にのみ設定する必要があります。

IFS='
'

ワイルドカードパターンを拡張したくない場合は、以下を使用して無効にする必要があります。

set -f

ただし、改行はファイル名のすべての文字と同じくらい有効であるため、通常、出力find -printは確実に後処理できません。

出力は次のとおりです。

./a.pdf
./b.pdf

現在のディレクトリのファイルとファイルを表すか、ディレクトリから呼び出されたファイルをa.pdf示します。b.pdfb.pdfa.pdf\n.

GNU(GNUに由来)findなどの一部の実装には、NL文字の代わりにNUL文字が続くファイル名を出力する述語があります。標準を使用すると、同じ結果が得られます。 NULは、ファイル名には現れない唯一の文字です。find-print0find-exec printf '%s\0' {} +

ただし、zsh変数にNUL文字(文字など)を格納できる唯一のシェルなので、$IFS次のようになります。

IFS=$'\0'
for i in `find ... -print0`; do
  ...
done

(コマンドを置き換えるとワイルドカードが実行されないため、inは必要ありません。)他のシェルでは機能しますが、set -f他のシェルでは機能しません。zshzshzsh

最も移植可能な方法は、findこれらのファイルから実行したいコマンドを呼び出すことです。 @Gnoucが提案したように:

find . -name '*.pdf' -exec the command {} \;

シェルステートメントに関連するより複雑な操作が必要な場合でも、次のことができます。

find . -name '*.pdf' -exec sh -c '
  for i do
    something complex with "$i"
  done' sh {} +

zshまたはを使用して、bash次のこともできます。

find . -name '*.pdf' -print0 |
  while IFS= read -r -d '' file; do
    whatever with "$file"
  done

ただし、ループ内の標準入力は影響を受けます。

zshfind(1990年以降)には、フレーズを通じてワイルドカード機能にほとんどの機能が含まれています。ここでは、任意のレベルのサブディレクトリ((*/)#文法またはより単純な形式)とワイルドカード修飾子(**/ウィジェットでは、...)を指定できます。-type f-mtime-permfind

その一部は2003年、2005年、2009年、2010年に再生産されました**/(このセクションも再現されましたが)。そして、それらのどれも基本的にアクティブではありません。残念ながら、およびはディレクトリ(/ inまたはin orなど)へのシンボリックリンクに従います。ksh93fishbashtcshtcsh***/bashfish **-L-followfind***zshtcsh

これらのシェルでは、ファイルに依存せずにすべてのレベルのサブディレクトリでファイルを見つけることができますが、上記の警告とglobbing修飾子にのみpdf注意してください。findfishbashzsh

たとえば、これは次のようzshになります。

find . -name '*.pdf' -type f -exec ls -ld {} +

する:

ls -ld ./**/*.pdf(D.)

これを使用するときは、bash次のことを行う必要があります。

shopt -s failglob
shopt -s globstar
files=(./**/*.pdf) &&
  for i do
    [ -f "$i" ] && ! [ -L "$i" ] && set -- "$i" "$@"
    shift
  done && ls -ld "$@"

おすすめ記事