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이는 각 디렉토리의 모든 경로 이름을 두 개의 배열로 가져오는 데 사용됩니다 . 그런 다음 배열에 있는 해당 경로 이름의 파일 이름 부분을 인쇄하는 것과 ls인쇄된 전체를 배열에서 제거하는 사이를 번갈아 가며 인쇄합니다. 배열 중 하나가 완전히 비어 있으면 중지됩니다.

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

만약 이것이라면실제로한 디렉터리의 파일이 다른 디렉터리의 해당 파일과 쌍을 이루도록 이름을 기반으로 파일을 쌍으로 연결하는 경우(생물정보학 응용 프로그램에서 가끔 수행되는 것으로 보임) 컬렉션 중 하나를 반복하는 것이 더 나을 것입니다.세워다른 그룹에 있는 해당 파일의 이름입니다.

파일이 호출되고 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}배열 압축운영자. 배열 중 하나의 요소 수가 다른 배열보다 적으면 해당 배열이 최소 길이로 잘린 것과 같습니다.

두 디렉터리의 파일 이름을 비교하려면 배열 교차 및 빼기 연산자도 참조하세요.

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

관련 정보