bash 분할 파일 목록 및 각 그룹에서 명령 실행

bash 분할 파일 목록 및 각 그룹에서 명령 실행

저는 bash와 코딩의 초보자이므로 양해해 주시기 바랍니다. 파일 목록(>1000)이 있고 이를 다른 형식으로 변환해야 합니다. 하지만 한 번에 40개의 파일에 대해 이 명령을 실행해야 합니다.

내가 시도한 것은 다음과 같습니다(그러나 이전에는 아무것도 없었기 때문에 기본적으로 명령을 실행하고 xargs가 작동하지 않습니다).

path=/home/dir1/dir2/dir3;
ls ${path} >> ${path}/LIST;
FILES=${path}/LIST;
xargs -n 40 <<$FILES | xargs commandname 

답변1

문제는 목록을 읽는 데 있습니다.

FILES=${path}/LIST;

~해야 한다

FILES=$(<"${path}/LIST")

하지만,

  • xargs파일을 직접 읽을 수도 있습니다 xargs -a "${path}/LIST".
  • xargs전혀 반복할 필요가 없습니다.
  • 파일 이름 변수는 항상 큰따옴표로 묶어야 합니다!
  • 경로에 공백이나 개행 문자가 포함되어 있으면 스크립트에 많은 문제가 발생하게 됩니다.
  • 파일을 찾을 수 없는 경우 인수 없이 명령을 실행하지 못하도록 추가되었습니다 -r.xargs

그래도,

파싱되지 않음ls.

대신 배열을 사용해야 합니다.

또한 파일 이름의 일부로 개행 문자와 관련된 문제를 방지하기 \0위해 구분 기호로 및 를 함께 사용하는 데 익숙해 지는 것이 좋습니다 .xargs -0

shopt -s nullglob # avoid `*` as file if no files found in $path
path=/home/dir1/dir2/dir3
files=("${path}"/*)
printf '%s\0' "${files[@]}" | xargs -0 -r -n40 commandname
shopt -u nullglob

또는 parallel대신 사용하십시오 xargs:

shopt -s nullglob
parallel -j1 -n40 commandname ::: /home/dir1/dir2/dir3/*

답변2

zsh를 바꾸 려면 ...을 사용하세요 bash.

autoload zargs
zargs -rl40 -- /home/dir1/dir2/dir3/*(nN) -- commandname

( 정렬 순서 n의 경우 일반적으로 번호 numericglobsort가 매겨진 파일에 더 좋습니다.file10뒤쪽에 file2예를 들어) 및 Nfor(따라서 nullglob일치하는지 여부에 대해 불평하지 않고 숨겨진 파일이 없거나 읽을 수 없는 경우 보관됩니다.)/home/dir1/dir2/dir3/*/home/dir1/dir2/dir3

답변3

나는 이와 같은 것이 GNU 확장을 사용하지 않고도 작동할 수 있다고 생각합니다.

set -- # clear positional arguments
for file in /home/dir1/dir2/dir3/*
do
    [ -e "$file" ] || continue
    set -- "$@" "$file"
    if [ "$#" -eq 40 ]
    then
        commandname "$@"
        set --
    fi
done
# in case the number of files is a number not divisible by 40
if [ "$#" -gt 0 ] && [ "$#" -lt 40 ]
then
    commandname "$@"
fi

명령이 무엇인지는 모르겠지만 다음과 같은 함수를 만들었을 때

commandname()
{
    printf 'received %d arguments\n' "$#"
    printf 'listing received filenames\n'
    counter=0
    for par in "$@"
    do
        counter="$(( counter+1 ))"
        printf 'argument number %d: %s' "$counter" "$par" | LC_ALL=POSIX tr -d '[:cntrl:]'
        printf '\n'              
    done
}

내가 알 수 있는 한, 수신된 메시지의 적절한 수를 표시하고 모두 올바르게 나열합니다. 여기에 나열된 대부분의 파일 이름을 테스트했습니다.쉘 스크립트의 파일 처리 견고성을 테스트하는 방법은 무엇입니까?(53개 파일).

또한 숨겨진 파일(점으로 시작하는 파일)은 찾을 수 없지만 OP에 작성한 내용도 찾을 수 없으므로 괜찮다고 생각합니다. 일반 파일만 필요한 -e "$file" ]경우 [ -f "$file" ].

답변4

find /home/dir1/dir2/dir3 -maxdepth 1 -print0 |
  xargs -0 -n 40 -P 0 commandname

파일 수가 40의 배수가 아닌 경우 commandname프로세스 중 하나가 40개의 매개변수로 실행되지 않습니다.

관련 정보