Bash:単一のFor Inループを使用して2つのリストを繰り返します。

Bash:単一のFor Inループを使用して2つのリストを繰り返します。

2つの独立したループがあるとしましょう。

for file1 in `ls Dir1/` ; do
    echo $file1
done

for file2 in `ls Dir2/` ; do
    echo $file2
done

シングルループ疑似コードで両方のディレクトリを繰り返したいと思います。

for file1 , file2 in `ls Dir1` , `ls Dir2`
do
    echo $file1
    echo file2
done

可能ですか?

答え1

whileファイル名に改行がないと仮定すると、適切な入力を持つループが操作を実行できます。

paste -d/ <(ls /var) <(ls /usr) |
  while IFS=/ read -r e u; do
    printf '%s\n' "$e $u"
  done

答え2

shopt -s nullglob

dir1names=( Dir1/* )
dir2names=( Dir2/* )

while [ "${#dir1names[@]}" -gt 0 ] &&
      [ "${#dir2names[@]}" -gt 0 ]
do

    printf '%s\n' "${dir1names[0]##*/}"
    printf '%s\n' "${dir2names[0]##*/}"

    dir1names=( "${dir1names[@]:1}" )
    dir2names=( "${dir2names[@]:1}" )
done

bashこれは、各ディレクトリのすべてのパス名を2つの配列に取得するために使用されます。次に、配列内の対応するパス名のファイル名部分を印刷することと、印刷されたls全体を配列から削除することを交互に印刷します。配列の1つが完全に空の場合は停止します。

シェルnullglobオプションを使用すると、一致しないワイルドカードパターンが拡張されていないままではなく、何も拡張されません。

テスト:

$ tree
.
|-- Dir1
|   |-- file-1
|   |-- file-2
|   |-- file-3
|   `-- file-4
|-- Dir2
|   |-- otherfile-1
|   |-- otherfile-2
|   |-- otherfile-3
|   |-- otherfile-4
|   |-- otherfile-5
|   `-- otherfile-6
`-- script.sh

2 directories, 11 files
$ bash script.sh
file-1
otherfile-1
file-2
otherfile-2
file-3
otherfile-3
file-4
otherfile-4

もしこれなら実際にあるディレクトリ内のファイルが別のディレクトリ内の対応するファイルとペアになるように名前に基づいてファイルをペアにリンクする場合(生物情報アプリケーションで時々実行されるように見える)、コレクションの1つを繰り返す方が良いでしょう。立てる別のグループ内の対応するファイルの名前。

ファイルが呼び出され、something_R1_more特定のファイルのペアが識別されるsomething_R2_more場所をsomething想定します。moreR1R2

for r1 in dir1/*_R1_*; do
    r2=${r1##*/}              # dir1/something_R1_more --> something_R1_more
    r2=dir2/${r2/_R1_/_R2_}   # something_R1_more      --> dir2/something_R2_more

    if [ ! -f "$r2" ]; then
        printf '%s not found\n' "$r2" >&2
        exit 1
    fi

    # process "$r1" and "$r2" here
done

答え3

あなたは平均です解析したくない出力ls

ここでは、(変数を引用せずにワイルドカードを無効にせずにコマンド置換を使用するためではなく、すでに構文を使用していますzsh)、次のことができます。zshbash

dir1_file_names=(dir1/*(N:t))
dir2_file_names=(dir2/*(N:t))
for f1 f2 (${dir1_file_names:^dir2_file_names})
  printf '%s\n' "f1: $f1, f2: $f2"

zsh複数の変数を繰り返すことができます。${a:^b}配列圧縮オペレーター。配列の1つの要素数が他の配列より少ない場合、その配列は最小長に切り捨てられたものと同じです。

両方のディレクトリのファイル名を比較するには、配列の交差演算子と減算演算子も参照してください。

file_names_in_both_dir1_and_dir2=(${dir1_file_names:*dir2_file_names})
file_names_only_in_dir1=(${dir1_file_name:|dir2_file_names})
file_names_only_in_dir2=(${dir2_file_name:|dir1_file_names})

答え4

以下のように、複数の変数の出力を単一の変数に保存できます。それがあなたに効果があることを確認してください

#!/bin/bash
cd /
for file1 in $(ls /usr/ ; echo "::::::NEXT:::::::" ; ls /sys/)
do
    echo $file1
done

関連情報