이 "for" 루프에 필요한 입력을 어떻게 얻을 수 있나요?

이 "for" 루프에 필요한 입력을 어떻게 얻을 수 있나요?

TOR에서 다운로드한 콘텐츠를 백업하기 위해 작은 스크립트를 작성했는데, 그 이유는 TOR가 자리 표시자 파일(원본 파일 이름이 포함된 0바이트 파일)과 실제 다운로드한 파일(원본 파일 + 확장자 .part)을 미리 병합하려고 시도하기 때문입니다. 모든 데이터가 손실됩니다.

.part이 스크립트를 보완하기 위해 다운로드가 완료된 후 백업 파일을 삭제하는 스크립트를 원합니다 . 문제는 다운로드한 파일 이름에 공백이나 특수 문자가 포함되는 경우가 많아 큰따옴표를 사용해야 한다는 것입니다. 이는 여러 파일을 다운로드할 때까지 잘 작동합니다. 그 시점에서 find모든 파일을 한 줄로 확장하고 일치 테스트 문이 없습니다. .

내 접근 방식이 모두 잘못되었을 수도 있지만 그렇지 않은 경우 명령의 개별 파일 이름을 어떻게 얻을 수 있습니까 rm?

#!/system/bin/sh
if [ ! -d /sdcard/Download/tordownloadbackup ]; then
mkdir /sdcard/Download/tordownloadbackup
fi
echo 'backing-up'
find /sdcard/Download/ -maxdepth 1 -name '*.part' -print -exec cp {} /sdcard/Download/tordownloadbackup/ \;

for f in "`find /sdcard/Download/tordownloadbackup/ -type f |rev |cut -c 6-100| cut -d / -f 1 |rev`"; do

if [ -s /sdcard/Download/"$f" ]; then
    if [ -f /sdcard/Download/tordownloadbackup/"$f".part ]; then
    rm /sdcard/Download/tordownloadbackup/"$f".part
    d="$f".part
    echo "deleting $d"
    fi
fi
done
sleep 300
~/run.sh

답변1

파일 이름에 줄 바꿈이 없다고 확신하는 경우 다음을 수행할 수 있습니다.

find /sdcard/Download/tordownloadbackup/ -type f -printf '%f\n' |
    awk '{ print substr($0,1,length($0)-5); }' |
    while IFS= read -r filename; do
        : ...
    done

경로의 모든 문자에 대한 일반적인 접근 방식은 다음과 같습니다.

find . -exec bash -c 'ls -l "$@"' bash {} +

답변2

이 명령은 다음과 같습니다.

for f in "`find /sdcard/Download/tordownloadbackup/ -type f | ...

어색하고 오류가 발생하기 쉽습니다. 인쇄된 파일 목록을 반복하는 것은 실제로 권장되지 않습니다 for.

Bash에서 찾은 파일을 반복하는 가장 안정적인 방법은 a 및 null로 끝나는 문자열을 find사용하는 것입니다 . read명령 출력을 파이핑한 < <(command)후 사용됩니다 .whileread프로세스 교체.

while IFS= read -r -d $'\0' file; do
    # Arbitrary operations on "$file" here
done < <(find /some/path -type f -print0)

이전 답변에 대해 @SiegeX에게 감사드립니다.https://stackoverflow.com/questions/8677546/reading-null-delimited-strings-through-a-bash-loop

게다가 rev |cut -c 6-100| cut -d / -f 1 |rev이상해 보이는데. 나는 이것이 디렉토리 기본 이름을 인쇄해야 한다고 생각합니다. 이렇게 하려면 bash에 내장된 문자열 조작 또는 dirnameand를 사용하세요.basename

따라서 이 루프를 다음과 같이 다시 작성하게 될 수도 있습니다(내장되어 있으므로 더 빠른 문자열 조작 사용).

while IFS= read -r -d $'\0' file; do
  Filebasename="${file##*/}"
  Dirname="${file%/*}"
  Dirbasename="${Dirname##*/}"
  # other stuff here
done < <(find /sdcard/Download/tordownloadbackup/ -type f -print0)

하위 문자열 제거에 대한 자세한 내용은 다음을 참조하세요.Linux 문서화 프로젝트.

또는 basename다음을 사용하십시오 dirname(외부 프로그램으로 인해 속도가 느려짐).

while IFS= read -r -d $'\0' file; do
  Dirbasename="$(basename -- "$(dirname -- "$file")")"
  # other stuff here
done < <(find /sdcard/Download/tordownloadbackup/ -type f -print0)

관련 정보