スペースとワイルドカードを含むパスを含む文字列でのbashスクリプトエラー


25

Bashスクリプトの基本を理解するのに苦労しています。ここに私が持っているものがあります:

#!/bin/bash
FILES="/home/john/my directory/*.txt"

for f in "${FILES}"
do
  echo "${f}"
done

私がやりたいのは、すべての.txtファイルをforループにリストすることです。しかし、中のスペースmy directoryとアスタリスクは*.txtうまく再生されていません。二重引用符の有無にかかわらず、変数名に中括弧の有無にかかわらず使用してみましたが、すべての.txtファイルを印刷できません。

これは非常に基本的なことですが、疲れてまっすぐに考えることができないため、私はまだ苦労しています。

何が間違っていますか?

ファイルにスペースやアスタリスクがなければ、上記のスクリプトを正常に適用することができました。しかし、スペースとアスタリスクの両方があると、すべてが台無しになります。

回答:


33

引用符内では、*ファイルのリストに展開されません。このようなワイルドカードを正常に使用するには、引用符の外にある必要があります。

ワイルドカードが展開された場合でも、式"${FILES}"はファイルのリストではなく単一の文字列になります。

動作する1つのアプローチは次のとおりです。

#!/bin/bash
DIR="/home/john/my directory/"
for f in "$DIR"/*.txt
do
  echo "${f}"
done

上記では、スペースまたはその他の難しい文字を含むファイル名は正しく処理されます。

より高度なアプローチでは、bash配列を使用できます。

#!/bin/bash
FILES=("/home/john/my directory/"*.txt)
for f in "${FILES[@]}"
do
  echo "${f}"
done

この場合、FILESはファイル名の配列です。定義を囲む括弧は、それを配列にします。*は引用符の外にあることに注意してください。構造"${FILES[@]}"は特殊なケースです。各文字列がファイル名の1つである文字列のリストに展開されます。スペースまたはその他の難しい文字を含むファイル名は正しく処理されます。


1
うまくいった
ジョン

関数を介してこのようなパスを渡す場合は、変数大きな文字列の一部として連結するのではなく 、変数自体を引用符で囲む必要があることに注意してください。for f in "$DIR"/*.txt= fine for f in "$DIR/*.txt"= breaks
pospi

7

John1024に示されている配列を使用する方がはるかに理にかなっていますが、ここではsplit + glob演算子を使用することもできます(スカラー変数を引用符で囲まずに残します)。

その演算子のグロブ部分のみが必要なため、分割部分を無効にする必要があります。

#! /bin/sh -
# that also works in any sh, so you don't even need to have or use bash

file_pattern="/home/john/my directory/*.txt"
# all uppercase variables should be reserved for environment variables

IFS='' # disable splitting

for f in $file_pattern # here we're not quoting the variable so
                       # we're invoking the split+glob operator.
do
  printf '%s\n' "$f" # avoid the non-reliable, non-portable "echo"
done

0

できることは、引用符の外にワイルドカード文字のみを残すことです。
のようなもの:
a for "files withスペ​​ース" * "。txt"

処理を
完了
しますワイルドカード自体がスペースに展開される場合、ls -lを使用して、ファイルを取得し、bash readを使用して各ファイルを取得します。


-1

ファイルのセットを処理する場合、名前がスペースであるか、他のスケープコードが存在する可能性があるため、プロセスを開始する前に、for loopまたはにfind command設定することを検討してくださいIFS bash env variable

IFS=$(echo -en "\n\b")
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.