grep エスケープファイル名の結果

grep エスケープファイル名の結果

bashがファイル名を正しく読み取れるように、grepの出力をどのようにエスケープしますか?

findコマンドの出力であるテキストファイルがあります。各行ごとにシンボリックリンクを作成したいと思います。今はループをテストしていますls。ただし、特殊文字については、grepの文字列出力を正しく引用しません。これにより、各ファイルのファイルシステムコマンドが失敗します。

$ tree dir/
dir/
├── Another & file ' name.txt
└── file name.txt

0 directories, 2 files

$ cat files.txt
dir
dir/Another & file ' name.txt
dir/file name.txt

$ grep file files.txt | awk -v q='"' '{printf(q"%s"q"\n", $0);}'
"dir/Another & file ' name.txt"
"dir/file name.txt"

$ while read p ; do 
    echo $p; ls $(grep file files.txt | awk -v q='"' '{printf(q"%s"q"\n", $0);}') ; 
done < files.txt
dir
ls: cannot access '"dir/Another': No such file or directory
ls: cannot access '&': No such file or directory
ls: cannot access 'file': No such file or directory
...
dir/Another & file ' name.txt
ls: cannot access '"dir/Another': No such file or directory
ls: cannot access '&': No such file or directory
ls: cannot access 'file': No such file or directory
...

一重引用符と二重引用符を使用してみました。 grepのパス出力でコマンドを実行するにはどうすればよいですか?

答え1

存在する

ls $(grep file file.txt)

分割+グローブ演算子を誤って使用しており、ここに問題があります。出力がシェルコードとして解釈されないので(ありがとう!)、出力に引用符を挿入したくありませんが、grep分割+グローブ演算子を調整する必要があります。

ここ

  1. *glob部分(例:現在のディレクトリのファイルリストに単語を拡張する)は必要ないので、次の方法で無効にする必要があります。

    set -o noglob
    
  2. grep出力を改行文字に分割するだけです(これはファイル名に改行文字を含めることはできませんが、これはfile.txtファイル形式の制限です)。

    IFS='
    '
    

    または

    IFS=$'\n'
    

    一部の殻では。

その後、引用符なしで分割+glob演算子を呼び出すことができますが、次のように$(...)なります。

ls -d -- $(grep file files.txt)

Split+glob 演算子は Bourne シェルから継承されたバグです。最新のシェルには、いくつかのテキストを行リストに分割する別の方法があります。

zshを使う:

ls -d -- ${(f)"$(grep file files.txt)"}

パラメータf拡張フラグは改行(改行)に分割されます。Fps:\n:'eed)は、その文字列内のエスケープシーケンスを理解するためにs:string:文字列を分割する略語です。私たちはSplit + glob演算子を無効にすると引用します。p\n$(...)zsh分ける部分(なし全体的な状況)。

そしてbash

readarray -t files < <(grep file files.txt)
ls -d -- "${files[@]}"

xargsasを使用する入力形式がスペースで区切られたリストである場合は、引用符を挿入できます。xargsここで、区切り文字は一重引用符、二重引用符、またはバックスラッシュで囲むことができます(ただし、シェル引用のような方法ではありません)。

だからあなたはこれを行うことができます:

 sed '
   s/"/"\\""/; # escape the " characters themselves
   s/^/"/;s/$/"/; # insert one at the beginning and one at the end
 ' < files.txt | xargs ls -d --

関連情報