誰かディレクトリ名のリストに対して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
はそれぞれの完全な名前をアトミックな単位とみなします
サブディレクトリに再帰的に移動したい場合、シェルに拡張グロブ機能 (bash
の globstar
のような) がない限り、これはできません。シェルにこれらの機能がない場合や、スクリプトが様々なシステムで動作するようにしたい場合は、次のオプションは 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