forループのコマンド置換は機能しません。

forループのコマンド置換は機能しません。

すべてのファイルをアーカイブしたい。いいえ次に終わる.bat

頑張った

for f in $(ls | egrep -v .bat); do echo $f; done

そして

for f in $(eval ls | egrep -v .bat); do echo $f; done

ただし、どちらの方法もすべての内容を印刷するため、同じ結果が得られます。ループ外で使用すると、それ自体ls | egrep -v .bateval ls | egrep -v .bat動作できますfor

編集する

興味深いことに、対応するフラグを省略すると、-vループは予想される操作を実行し、で始まるすべての項目を一覧表示します.bat


質問が何であるかわからないので、質問のタイトルを自由に編集してください。

私はそれを使用していますGNU bash, version 4.1.10(4)-release (i686-pc-cygwin).


はい

$ ls -l | egrep -v ".bat"
total 60K
-rwx------+ 1 SYSTEM SYSTEM 5.3K Jun  6 20:31 fsc*
-rwx------+ 1 SYSTEM SYSTEM 5.3K Jun  6 20:31 scala*
-rwx------+ 1 SYSTEM SYSTEM 5.3K Jun  6 20:31 scalac*
-rwx------+ 1 SYSTEM SYSTEM 5.3K Jun  6 20:31 scaladoc*
-rwx------+ 1 SYSTEM SYSTEM 5.3K Jun  6 20:31 scalap*

コマンドは実行中ですが、forループ内にありません。

$ for f in $(ls | egrep -v .bat); do echo $f; done
fsc
fsc.bat
scala
scala.bat
scalac
scalac.bat
scaladoc
scaladoc.bat
scalap
scalap.bat
scalac
scalac.bat
scaladoc
scaladoc.bat
scalap
scalap.bat

デバッグ $ set -x

mike@pc /cygdrive/c/Program Files (x86)/scala/bin
$ for f in $(ls | egrep -v .bat); do echo $f; done
++ ls -hF --color=tty
++ egrep --color=auto -v .bat
+ for f in '$(ls | egrep -v .bat)'
+ echo fsc
fsc
+ for f in '$(ls | egrep -v .bat)'
+ echo fsc.bat
fsc.bat
// and so on

答え1

コードにいくつかのエラーがあります。

$(...)設定なしで引用符で囲まれていないコマンドの置き換え()を使用する$IFS

分割+グローブ演算子は引用符なしで拡張されます。デフォルトはスペース、タブ、改行に分割することです。ここでは改行文字のみに分割したいので、IFSをその値に設定する必要があります。それ以外の場合、ファイル名にスペースやタブが含まれていると機能しません。

引用符なしでコマンド置換を使用しますset -f

分割+グローブ演算子は引用符なしで拡張されます。ここではワイルドカードは必要ありません。つまり、ワイルドカードをscala*一致するファイルのリストに拡張することです。シェルがグローブを実行しないようにするには、次のようにシェルを無効にする必要があります。set -f

lsニックネームls -F

ls上記の問題は、エイリアスを使用したという事実によってさらに悪化しますls -F/ディレクトリと*実行可能ファイルに追加されます。したがって、通常はscala実行可能ファイルls -Fであり、scala*グローブパターンであるため、そのファイルで始まるすべてのファイル名に展開されます。scalaこれはegrep -v、ファイルをフィルタリングしないように見える理由を説明します。

ファイル名に改行文字が含まれていないとします。

改行文字は、ファイル名のすべての文字と同じくらい有効です。だからls一般的に機能しない出力の解析。たとえば、という名前のファイルを含むディレクトリの出力は、という名前のファイルをls含むaディレクトリbの出力と同じですa\nb

上記は、egrepファイル名ではなくファイル名の行をフィルタリングします。

egrep代わりに使用grep -E

egrep廃止予定です。grep -E標準等価値です。

.正規表現演算子をエスケープしないでください。

上記でegrep有効にしました。拡大する正規表現ですが、拡張 RE 関連演算子は使用しません。あなたが使用する唯一のRE演算子は、.必要な文字のようには見えませんが、すべての文字を一致させることです。だからあなたgrep -Fもこれを使ったかもしれません。またはgrep -v '\.bat'

正規表現を行末に固定しないでください。

egrep .bat後に文字を含むすべての行と一致するため、batこの正規表現はbat最初の場所に含まれていないすべての項目を意味します。そうしたはずだったgrep -v '\.bat$'

$f引用なし

引用符のない拡張は、分割+グローブ演算子です。ここではどちらも望まないので、$f引用符()で囲む必要があります"$f"

使用echo

echo引数でANSI Cエスケープシーケンスを拡張するか、実装(および/または環境)-nに従って特別に文字列を処理します。-eecho

printf代わりに使用

したがって、より良い解決策は次のとおりです。

for f in *; do
  case $f in
    (*.bat);;
    (*) printf '%s\n' "$f"
  esac
done

ただし、現在のディレクトリに隠されていないファイルがない場合、出力は依然として出力されます。に変更するか、を実行して*問題を解決できます。zsh**(N)bashshopt -s nullglob

答え2

このようにファイルを解析しないでくださいls

まず、extglob globstarを設定してshopt -s extglob globstarから

for f in !(*.bat)
  do
   printf '%s\n' "$f"
  done

使用find

find . -type f ! -name '*.bat' 

ファイルをより安全に処理するには、否定演算子を使用してください。

答え3

forループには本質的に間違ったものはありません。

$ for f in $(ls | egrep -v .bat); do echo $f; done

上記のコマンドの結果は次のとおりです。

$ for f in $(ls | egrep -v .bat); do echo $f; done
fsc
scala
scalac
scaladoc
scalap

可能な修正

1つの提案は、次のようにパラメータを引用することですegrep

$ for f in $(ls | egrep -v '.bat'); do echo $f; done

Bashでスクリプトを作成するときに発生する可能性がある他の潜在的な問題については、Bash Pitfalls Wikiを確認することもできます。特にそのような音がするなら最も合理的な理由なぜこの問題が発生しますか?返されたファイルにスペースが含まれていることを確認してください。

デバッグ

もう一度試すもう1つの方法は、bashコマンドを実行する前に詳細なデバッグを有効にして、後で何が起こっているかを確認することです。

これによりデバッグが可能になります。

$ set -x

その後、コマンドを実行します。

$ for f in $(ls | egrep -v .bat); do echo $f; done
++ ls --color=auto
++ egrep --color=auto -v .bat
+ for f in '$(ls | egrep -v .bat)'
+ echo fsc
fsc
+ for f in '$(ls | egrep -v .bat)'
+ echo scala
scala
+ for f in '$(ls | egrep -v .bat)'
+ echo scalac
scalac
+ for f in '$(ls | egrep -v .bat)'
+ echo scaladoc
scaladoc
+ for f in '$(ls | egrep -v .bat)'
+ echo scalap
scalap

その後、無効にします。

$ set +x

CYGWIN質問がありますか?

bashこれらの例が多くの基本的なLinuxシステムでうまく動作することを考えると、問題はCygwinおよび/またはその特定のバージョンに関連している可能性が高いですegrep$IFSWindows()とUnix()のさまざまな行区切り文字に問題があるかどうかを確認するために、Bashのフィールド区切り文字に特別な注意を払います。0x0d,0x0a0x0a

私はCygwinをインストールしていないので、この仮説を証明する方法はありません。

関連情報