定義されたディレクトリの範囲内でコマンドを実行します。

定義されたディレクトリの範囲内でコマンドを実行します。

各「範囲」で異なるタスクを実行するために、ディレクトリリストを特定の数のチャンクに「分割」できますか?

たとえば、別のフォルダに次のディレクトリがあるとします。

$ ls test
abc/
def/
hij/
klm/
nop/
qrs/
tuv/
wxy/
zzz/

最初の3つのディレクトリに対していくつかのタスクを実行し、最後の3つのディレクトリに対して他のタスクを実行したいと思います。

同様の結果に基づいて、私の考えでは、数字を横切るループが機能する可能性があります。 (しかし、誰かが言及する前に、解析は絶対にならないことをls | nl知っています!)ls

これは明らかに動作しません。しかし、私はポイントを明らかにしたいと思います。

for dir in `ls | nl`; 
do
    do-something-with ${dir{1..3}} # Where $dir has taken on some numerical value linked to the folder)
    do-something-with ${dir{4..6}} 
# And so on...
    do-something-with ${dir{n-3..n}} 
done

実際には、これを実行したいフォルダは任意の順序で処理できます(つまり、最終的な分割は完全に任意である可能性があります)、論理的な名前付けの一貫性はありません。つまり、ディレクトリ名によってアルファベット順や数値順で合理的に構成できないという意味です。それ自体。

答え1

次のいずれかを行う理由はありません。間違いこの場合:

  1. 移植不能なGNU拡張の使用(例xargs -0:)
  2. ファイル名だけをテキストストリームに解析し、改行を含めることができないように偽装します。

この問題は困難なく簡単に処理できます。

set -- */
while [ "$#" -gt 0 ]; do
  case "$#" in
    1)
      my-command "$1"
      shift 1
      ;;
    2)
      my-command "$1" "$2"
      shift 2
      ;;
    *)
      my-command "$1" "$2" "$3"
      shift 3
      ;;
  esac
done

実際、これは必要以上に冗長ですが、この方法で読むことができます。

さまざまな種類のパーティションに対してすべてのディレクトリを3つの異なる処理方法に分割したい場合(ただし、同時に処理する必要はありません)、次のことができます。

x=1
for d in *; do
  [ ! -d "$d" ] && continue
  case "$x" in
    1)
      # do stuff with "$d"
      ;;
    2)
      # do stuff with "$d"
      ;;
    3)
      # do stuff with "$d"
      ;;
  esac
  x=$(($x+1))
  [ "$x" -eq 4 ] && x=1
done

答え2

そしてprintf/xargs

printf "%s\0" */ | xargs -0 -n3 echo do-something
  • printf現在のディレクトリの内容を印刷します(スペースで区切ります)。末尾のスラッシュは*ファイルではなくディレクトリにのみ一致します。
  • xargsNullで区切られた入力を読む-0
    • -n3入力を3つの部分に分割します。

出力(例ディレクトリを含む):

do-something abc/ def/ hij/
do-something klm/ nop/ qrs/
do-something tuv/ wxy/ zzz/

答え3

時には-nこれにはtoパラメータを使用できます。xargsジョブを並列に実行したい場合でも、-Pこのオプションを使用できます。

/tmp/t$ ls -1
dir1
dir2
dir3
dir4

/tmp/t$ ls -1 |xargs -n 3 echo runcmd
runcmd dir1 dir2 dir3
runcmd dir4

解析された出力についてあまり心配しないでくださいls|nl。これらのことを心配する必要がある場合は、xargsfind .. -print0パラメータを使用できます-0。 (両方が利用可能であると仮定)。

答え4

ワイルドカードのソリューションは私が使ったソリューションなので、彼の答えを承認されたとマークしましたが、後でこの問題を偶然発見した人に役立つ場合に備えて、他の11のディレクトリディレクトリコードに330を均等に配布する方法は次のとおりです。 。 。

それはまた非常に速く見えることを指摘する価値があるでしょう!

#!/bin/bash

numdirs=11

for ((i=1; i<=$numdirs; i++))
do
    mkdir -p ~/simulation_groups/group_${i}
done

x=1

for d in * ; do
  [ ! -d "$d" ] && continue
  case "$x" in
1)
  mv $d ~/simulation_groups/group_${x}
  ;;
2)
  mv $d ~/simulation_groups/group_${x}
  ;;
3)
  mv $d ~/simulation_groups/group_${x}
  ;;
4)
  mv $d ~/simulation_groups/group_${x}
  ;;
5)
  mv $d ~/simulation_groups/group_${x}
  ;;
6)
  mv $d ~/simulation_groups/group_${x}
  ;;
7)
  mv $d ~/simulation_groups/group_${x}
  ;;
8)
  mv $d ~/simulation_groups/group_${x}
  ;;
9)
  mv $d ~/simulation_groups/group_${x}
  ;;
10)
  mv $d ~/simulation_groups/group_${x}
  ;;
11)
  mv $d ~/simulation_groups/group_${x}
  ;;
  esac
  x=$(($x+1))
  [ "$x" -eq $numdirs+1 ] && x=1
done

関連情報