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

おすすめ記事