Bash forループ、文字列varにスペースが含まれています。

Bash forループ、文字列varにスペースが含まれています。

私のディレクトリには、空白のある2つのファイルfoo baranother file空白のない2つのファイルがありますfile1file2

次のスクリプトが機能します。

for f in foo\ bar another\ file; do file "$f"; done

このスクリプトは、次のような場合でも機能します。

for f in 'foo bar' 'another file'; do file "$f"; done

ただし、次のスクリプトは機能しません。

files="foo\ bar another\ file"
for f in $files; do file "$f"; done

このスクリプトも機能しません。

files="'foo bar' 'another file'"
for f in $files; do file "$f"; done

しかし、ファイルに空白がない場合、スクリプトは機能します。

files="file1 file2"
for f in $files; do file "$f"; done

ありがとうございます!

編集する

私のスクリプトのコードスニペット:

while getopts "i:a:c:d:f:g:h" arg; do
  case $arg in
    i) files=$OPTARG;;
    # ...
  esac
done

for f in $files; do file "$f"; done

空白のないファイルの場合、私のスクリプトは機能します。しかし、次のいずれかの方法でスペースを含むファイルをパラメータとして渡すスクリプトを実行したいと思います。

./script.sh -i "foo\ bar another\ file"
./script.sh -i foo\ bar another\ file
./script.sh -i "'foo bar' 'another file'"
./script.sh -i 'foo bar' 'another file'

ベストアンサー1

以下を使用する場合は、bash配列を使用できます。

#!/bin/bash
files=('foo bar' 'another file' file1 'file2')
for f in "${files[@]}"; do file -- "$f"; done

スペースまたはシェル構文の他の特殊文字(たとえば;、、|など)を含むファイル名は、引用符で囲む必要があります。&*

ワイルドカード(、、、および一部のバージョンでは有効になっている場合は多い)または文字(スペース、タブ、および改行)ファイル名のデフォルト値を含めるには、少なくともリストコンテキスト(in"${files[@]}"やhereなど)の拡張子の周囲に二重引用符が必要です。 。"$f"*?[\bashextglob$IFS

これらの文字を含まず、ASCII以外の文字を含まないファイル名の場合はオプションです(推奨)。

ファイルのリストが現在の作業ディレクトリから来ている場合は、必要に応じてワイルドカードを使用できます。たとえば、名前に含まれるファイルやディレクトリをfiles=(*f*)一致させる場合は、一致しない場合はリテラルを事前にインポートしないようにしたいと思います。 (しかし、配列を完全に使用または避けることもできます)。fshopt -s nullglob*f*for f in *f*; do...done

--タグは、fileダッシュで始まる場合でも、後続の引数がファイル名であることを示します。

man bash(検索Arrays)を使用するか、詳細をお読みくださいinfo bash arrays

おすすめ記事