シェルスクリプトで2つの反復可能なオブジェクトのセットを繰り返すには?

シェルスクリプトで2つの反復可能なオブジェクトのセットを繰り返すには?

通常、特定のタスク用のシェルスクリプトを作成するときに、次のファイルのリストを作成します。

#/bin/sh
read -d '' imagefiles <<EOF

./01/IMG0000.jpg
./01/IMG0001.jpg
./01/IMG0002.jpg
./01/IMG0003.jpg
./01/IMG0004.jpg
./01/IMG0005.jpg
./01/IMG0006.jpg
./01/IMG0007.jpg
(a whole bunch of files down to ./10/IMG0102.jpg)

EOF

for i in $imagefiles
  for j in range(len(commands))
do

mv $i ./$j.jpg

  done
done

この場合、出力を繰り返すことができるようにしたいのですが、Gillesが提案したように、seqこの部分をPythonで書いてください(例えば、各コマンドがj回実行されて約100,000回実行されることを知っています)。以前は736個のファイルを順番に名前を変更しましたが、今では名前を変更するファイルが1000個を超えています。これを行うより良い方法があると確信していますが(躊躇しないでください)、コマンドリストと他の繰り返し可能な項目を繰り返す方法を知ることもできます。

答え1

いいですね。 2つの反復可能項目を圧縮しようとしています。つまり、追加のカウンタを使用して複数の文字列を繰り返すループが必要です。カウンターを実装するのはとても簡単です。

n=0
for x in $commands; do
  mv -- "$x" "$n.jpg"
  n=$(($n+1))
done

これは、繰り返したい要素にスペース(またはワイルドカード)が含まれていない場合にのみ機能します。項目が改行で区切られている場合は、ワイルドカードをオフにして改行に分割します。

n=0
IFS='
'; set -f
for x in $commands; do
  mv -- "$x" "$n.jpg"
  n=$(($n+1))
done
set +f; unset IFS

データを一度だけ繰り返す必要がある場合は、ループを実行してくださいread(参照:while IFS= read代わりに、なぜそれほど頻繁に使用されますかIFS=; while read..詳細な説明は)

n=0
while IFS= read -r x; do
  mv -- "$x" "$n.jpg"
  n=$(($n+1))
done <<EOF
EOF

配列(bash、ksh、またはzsh)を持つシェルを使用している場合は、配列に要素を保存します。 zshでsetopt ksh_arrays0から始まる番号付き配列要素を実行するか、1から始まる配列要素番号付けを開始するようにコードを調整します。

commands=(
    ./01/IMG0000.jpg
)
n=0
while [[ $n -lt ${#commands} ]]; do
  mv -- "${commands[$n]}" "$n.jpg"
done

答え2

シェルがある場合、bashこのプログラムを実行する必要はありませんseq。ただ使用

for i in {1..736}
  do

前にゼロのあるシーケンスが必要な場合は{001..736}(even {0001..0736})のみを使用してください。

また、可能であればバックティック(これがどのように物事を混乱させるかについては、この質問を参照してください。)。

もう1つのことは、ファイルグループを操作したい場合にこの機能が役に立つ可能性があることです。

for file in /some/path/*
  do

すべてのファイルで動作します(およびフォルダ)ディレクトリに/some/path/。範囲をファイルに絞り込むには、次のような[ -f "$file" ]同様のテストを使用できます。

for file in /some/path/*
  do
  [ -f "$file" ] || continue
  (do your stuff here)

また、設定/some/path/*はのようなシェルモードで調整できます。/some/path[123]/*/some/path[A-Z]/b*[e-g]*/some/path{1,5,23}/*

質問の最初の部分については、次のようにネストされたfor(または任意の)ループを使用できます。while

for cm in $commands; do
 for file in /some/path[ab]{1,4,2}/*.log; do
    mv "${file}" "${file//text/replacement}"
 done
done

答え3

Bashでは、複数の操作を並列に繰り返すことはできないと思います。

始めましょうi=1。その後、ファイルのリストが繰り返され、let i=$i+1ループに含まれます。$i -ge 736また、ループカウント後に入力された項目の繰り返しを停止したい場合は、ループを停止するテストも含まれます。

i=0
for file in ./{01..10}/*jpg; do
    let i=$i+1
    mv "$file" "$i-$file"
done

Xファイルを閉じようとすると、次のテストを使用できます。

[[ $i -ge 736 ]] && return || let i=$i+1

答え4

Bashは配列をサポートしています:

http://tldp.org/LDP/abs/html/arrays.html

または

COUNT=0
for i in `ls *.txt`
do
  COUNT=`expr $COUNT + 1`
  mv "$i" "$COUNT-$i"
done

これにより、a.txt b.txt c.txt ファイルの名前が 1-a.txt 2-b.txt 3-c.txt に変更されます。

関連情報