ls` をループすると bash シェルスクリプトになります

bash shell shell-script

誰かディレクトリ名のリストに対してlsで何かをして、それぞれをループして何かをするためのシェルスクリプトのテンプレートを持っている人はいますか?

ディレクトリ名の一覧を取得するためにls -1d */をしようと思っています

  120  None  2009-08-28


ベストアンサー

shawn-j-goff や他の人が提案したように、グロブが可能な場所では ls を使わないように編集しました

for..do..doneのループを使えばいいだけです

for f in *; do
echo "File -> $f"
done

**.txtに置き換えたり、リスト(ファイル、ディレクトリ、その他何でも)を返す他のグロブ、リストを生成するコマンド、例えば$(cat filelist.txt)のようにリストを生成するコマンド、または実際にリストに置き換えることができます

do ループ内では、ドル記号の接頭辞でループ変数を参照します (上の例では $f)。echo ループ内では、echo ループ変数を参照したり、他に何かをしたりすることができます

例えば、カレントディレクトリ内のすべての.xmlファイルの名前を.txtに変更します

for x in *.xml; do
t=$(echo $x | sed 's/\.xml$/.txt/');
mv $x $t && echo "moved $x -> $t"
done

あるいは、Bash を使用している場合は、サブシェルをスポーンするのではなく、Bash のパラメータ拡張を使用することもできます

for x in *.xml; do
t=${x%.xml}.txt
mv $x $t && echo "moved $x -> $t"
done

140  Gene Gotimer  2009-08-28


lsの出力を使ってファイル名を取得するのはよくない考えですそれは誤動作や危険なスクリプトにつながる可能性があります。これは、ファイル名には /null 文字以外の任意の文字を含むことができ、ls はこれらの文字のどちらも区切り文字として使用しないため、ファイル名にスペースや改行がある場合、予期しない結果を得ることになるからです

ファイルの反復処理には二つの良い方法があります。ここでは、単に echo を使って、ファイル名を使って何かをすることを示しています

1つ目は、シェルのネイティブなグロブ機能を使用することです

for dir in */; do
echo "$dir"
done

シェルは */ を展開して for ループが読み込んだ別の引数に展開します; ファイル名にスペースや改行、その他の奇妙な文字があっても、for はそれぞれの完全な名前をアトミックな単位とみなします

サブディレクトリに再帰的に移動したい場合、シェルに拡張グロブ機能 (bashglobstar のような) がない限り、これはできません。シェルにこれらの機能がない場合や、スクリプトが様々なシステムで動作するようにしたい場合は、次のオプションは find を使うことです

find . -type d -exec echo '{}' \;

ここでは、findコマンドはechoを呼び出し、ファイル名の引数を渡します。これは、見つけたファイルごとに一度だけ行われる。前の例のように、ファイル名のリストを解析することはありません; 代わりに、ファイル名は完全に引数として送られます

-execの引数の構文は少しおかしいように見えます。find-exec の後の最初の引数を取り、それを実行するプログラムとして扱い、それ以降のすべての引数は、そのプログラムに渡す引数として受け取ります。-execが見なければならない特別な引数が2つあります。最初の引数は {} で、この引数は find の前の部分が生成するファイル名に置き換えられます。2番目の引数は ; で、これがプログラムに渡す引数のリストの終わりであることを find に知らせるものです; find はこれを必要とします。\の理由は、シェルが;を特別に扱うからです – これはコマンドの終わりを表しているので、シェルがそれ自体を消費するのではなく、findの引数として与えるように、これをエスケープする必要があります。';'\; と同様にこの目的に適しています

72  Shawn J. Goff  2012-04-29


スペースを含むファイルの場合は、次のように変数を引用しなければなりません

 for i in $(ls); do echo "$i"; done;

または、入力フィールドセパレータ(IFS)環境変数を変更することができます

 IFS=$'\n';for file in $(ls); do echo $i; done

最後に、あなたが何をしているかによっては、ls を必要としない場合もあります

 for i in *; do echo "$i"; done;

20  john  2009-08-28


GNU Parallel http://www.gnu.org/software/parallel/ がインストールされていれば、これを行うことができます

ls | parallel echo {} is in this dir

すべての.txtの名前を.xmlに変更します

ls *.txt | parallel mv {} {.}.xml

GNU Parallelの紹介ビデオを見てください。http://www.youtube.com/watch?v=OpaiGYxkSuQ

4  Ole Tange  2010-08-22


CoverosGeneさんの回答に補足するだけで、ディレクトリ名だけをリストアップする方法は以下の通りです

for f in */; do
echo "Directory -> $f"
done

4  n3o  2015-02-11


IFSを改行に設定して、lsの出力を配列に取り込んではどうでしょうか?IFSを改行に設定することで、ファイル名の変な文字の問題を解決することができます; lsを使用すると、ソート機能が組み込まれているので良いでしょう

(テストではIFSを\nに設定するのに苦労しましたが、他の場所で提案されているように、改行バックスペースに設定するとうまくいきます)

例:(lsの検索パターンが$1で渡されたと仮定して)

SAVEIFS=$IFS
IFS=$(echo -en "\n\b")

FILES=($(/bin/ls "$1"))

for AFILE in ${FILES[@]}
do
... do something with a file ...
done

IFS=$SAVEIFS

これはOS Xでは特に便利で、例えば、作成日(古いものから新しいものまで)でソートされたファイルのリストをキャプチャするには、lsコマンドはls -t -U -rになります

1  jetset  2012-05-10


コマンドラインで ls コマンドを使用して while ループを実行します


ls | while read filename;do echo "file name is $filename"; done

0  dılo sürücü  2020-10-06


完璧にいいですよ

#!/bin/sh
for i in `ls`
do
echo `ls -l $i`
done

こちらが出力です

root@online:/usr/local/httpd/bin # more ~root/rm-in-ls.sh
#!/bin/sh
for i in `ls`
do
echo `ls -l $i`
done

root@online:/usr/local/httpd/bin # /root/rm-in-ls.sh
-rwxr-xr-x 1 root wheel 82516 Jul 3 04:52 ab
-rwxr-xr-x 1 root 40 3431 Jul 3 04:35 apachectl
-rwxr-xr-x 1 root 40 23881 Jul 3 04:35 apxs
-rwxr-xr-x 1 root wheel 21456 Jul 3 04:52 checkgid
-rwxr-xr-x 1 root 40 8931 Jul 3 04:35 dbmmanage
root@online:/usr/local/httpd/bin #

見逃した!そうだ!

頭を上げろ!

ls’ の ” ‘ ‘ ではありません!ls’ の ” ` ” ではありません。アポストロフィではなく、アキュートです。’ と ` の間には違いがあります。私は大学時代(1990年)にそれを理解するのに一週間を費やしました

これは”`”ですが、〜ティルデはほとんどシフト+〜でキー、それはacute.wikiと呼ばれています

もし取得できなかった場合は、スクリプトをコピペして実行してください

-2  Biddut Mitra  2020-07-01


このようにしていますが、もっと効率的な方法があるのではないでしょうか

ls > filelist.txt

while read filename; do echo filename: "$filename"; done < filelist.txt

-3  TREE  2009-08-28


タイトルとURLをコピーしました