シェルスクリプトで名前にスペース(空白)を含むファイルがxargsでうまく処理できない場合の対処
はじめに
チームメンバから「名前にスペースを含むファイルをxargsでうまく取り扱えない」という相談を受けました。
調べたらすぐに解決する あれ だと思ったのですが、 find
ではなく grep
の実行結果を xargs
に渡していたので、なるほどあまり見ないケースだなと思ったついでにエントリをまとめました。
検証環境
"名前にスペース(空白)を含むファイルがxargsでうまく処理できない" とはどんな問題?
シェルあるあるではありますが 、実際にどんな問題なのか見ていきます。
まずは、ファイルを3つ作成します。それぞれ以下の名前とします。
hello1.txt
hello 2.txt
hello 3.txt
ここで find
コマンドを使ってファイルの一覧を xargs
に渡して echo
を実行させてみます。
-n 1
は標準入力の内容を1つずつ処理するオプションです。
悲しいことに hello 2.txt
、 hello 3.txt
というファイル名が分割して出力されました。 xargs
は標準入力からもらった内容を 改行 や 空白 で区切って処理するためです。
説明するだけで長くなりましたね。 これを解決するための方法を紹介します。
対処法 : find
コマンドの実行結果をxargsで処理する場合
find
コマンドには -print0
というオプションがあります。
オプションなしの場合は以下のように改行区切りでファイル名が出力されます。
ここで -print0
オプションを付与すると以下のように出力内容が変わります。
ターミナル上はわからないのですが、区切り文字が改行から null文字 ( \0
) と言われる特殊な文字に変わります。
この状態で xargs
に渡してみましょう。
少しだけ出力内容が変わりました。 「xargs
コマンド実行しているけど、 --null
文字つけたかったんじゃないの?」と。
xargs
に --null
オプションを付与すると、デフォルトの区切り文字を 改行 や 空白 ではなく null文字 ( \0
) を使うようになります。
ちなみに、 -0
オプションも同じ意味になります。
ここまではよくあるケースですね。
対処法 : grep -l
コマンドの実行結果を xargs
で処理する場合
grep -l
というコマンドで、 grep
で検索して該当したファイルの名前だけを出力させることができます。
先程作成した3つのファイルに適当なデータを格納しておきます。
ファイルの中身は以下のようになります。
ここで、 10 という数値を含むファイルだけを検索するためには以下のコマンドを実行します。
この結果を xargs
に渡して echo
しようとすると、 find
と同じ問題に直面します。
解決方法も find
と同じです。 --null
オプションというものが用意されており、これを利用します。
tar
コマンドにも xargs
と同じようにnull文字を区切り文字として受け取るオプションがある
xargs
だけではなく、 tar
コマンドにも圧縮対象のファイルを標準入力から受け取る際に null文字 を区切り文字として利用するオプションがあります。
過去のエントリでもサラリと紹介していました
ひとこと
grep
より高速と言われる ag
コマンドというものがありますが、やはり同じようなオプションが用意されています。
ファイル名を標準出力に出力するコマンド 、 ファイル名を標準入力から受け取るコマンド には、 大体区切り文字として null文字 を利用するためのオプションがあるのでしょう。
他にもコマンド、オプションを見つけた方はコメント下さい!
ディスカッション
コメント一覧
まだ、コメントがありません