すべてのファイルをアーカイブしたい。いいえ次に終わる.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 .bat
でeval 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
に従って特別に文字列を処理します。-e
echo
したがって、より良い解決策は次のとおりです。
for f in *; do
case $f in
(*.bat);;
(*) printf '%s\n' "$f"
esac
done
ただし、現在のディレクトリに隠されていないファイルがない場合、出力は依然として出力されます。に変更するか、を実行して*
問題を解決できます。zsh
*
*(N)
bash
shopt -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
。$IFS
Windows()とUnix()のさまざまな行区切り文字に問題があるかどうかを確認するために、Bashのフィールド区切り文字に特別な注意を払います。0x0d,0x0a
0x0a
私はCygwinをインストールしていないので、この仮説を証明する方法はありません。