Bash 스크립트 일반 문제 [닫기]

Bash 스크립트 일반 문제 [닫기]

제가 작업 중인 첫 번째 부분은 bash 셸에서 사용할 수 있는 모든 명령의 텍스트 파일 복사본이 포함된 command_manuals라는 폴더를 만드는 것입니다. 파일 이름은 명령 이름 자체입니다. 목표를 달성하는 스크립트에 영향을 주지 않는 일부 예외 오류 메시지를 제외하고 이 부분을 얻을 수 있었지만 가장 심각한 문제를 먼저 논의하는 것을 선호하므로 지금은 그대로 두겠습니다.

사용 가능한 매뉴얼이 없는 사람들은 여전히 ​​빈 텍스트 파일을 가지고 있는데, 이는 두 번째 부분의 목표로 이어집니다. 이 "0 크기 텍스트 파일"을 제거하고 나중에 사용하고 싶은 단일 목록을 컴파일하는 것입니다. apt-update를 할 때마다 "Undocumented man 7"을 확인하는 부분과 다른 사람들은 잘 알려진 패턴 검색 패키지 중 하나를 사용하여 설명서에 없는 ra, ra, ra 명령에 대해 새로운 것이 추가되었는지 확인합니다. 어쨌든 중요하지 않습니다. 두 번째 부분의 드라마를 지나갈 때까지 지금까지 크기가 0인 폴더 내용의 하위 집합만 인쇄하는 for 루프에 if 조건을 성공적으로 작성했지만 이 내용을 다시 재생하려고 하면 기본적으로 "then"과 "fi" 사이의 명령을 에코하면 빈 파일이 삭제되면서 문제가 시작됩니다.

그러나 그것은 또한 내가 발견한 또 다른 이상한 점과 관련된 추가 질문을 가져왔습니다. 그것은 내가 원하는 방식으로 작동하는 기본 템플릿 스크립트에 표준 #!/bin/bash 가 누락되어 있다는 것입니다. 내 .sh 스크립트 줄, 왜?

template_for_if_delete.sh

TOTALnum=$(wc -l < filesizes.txt);
for i in `seq 1 $TOTALnum`;
do
size=$(sed -n ''$i','$i'p' filesizes.txt)
if [ $size -eq 0 ];
then
echo $(sed -n ''$i','$i'p' filenames.txt);
fi
done;

지금까지실제두 번째 작업을 위한 스크립트:

2부.sh

#!/bin/bash
cd;
cd command_manuals;
rm filenames.txt;
ls -1 > filenames.txt;
TOTALnum=$(wc -l < filenames.txt);
for i in `seq 1 $TOTALnum`;
do filename=echo $(sed -n ''$i','$i'p' filenames.txt);
size=$(stat -c '%s' $filename);
if [ $size -eq 0 ];
then
rm $(locate $(sed -n ''$i','$i'p' filenames.txt));
fi
done;

출력을 생성합니다(위의 for 루프에 정의된 횟수만큼 반복됨).

Try 'stat --help' for more information.
./secondpart.sh: line 9: [: -eq: unary operator expected
./secondpart.sh: line 8: x86_64-linux-gnu-gold.txt: command not found
stat: missing operand

그런 다음 if 문의 변수 "size"를 복잡한 매개변수 확장으로 변경해 보았습니다.

#!/bin/bash
cd;
cd command_manuals;
rm filenames.txt;
ls -1 > filenames.txt;
TOTALnum=$(wc -l < filenames.txt);
for i in `seq 1 $TOTALnum`;
do filename=echo $(sed -n ''$i','$i'p' filenames.txt);
size=$(stat -c '%s' $filename);
if [ ${#size} -eq 0 ];
then
rm $(locate $(sed -n ''$i','$i'p' filenames.txt));
fi
done;

관련 없는 임의의 항목을 삭제하고 싶은지 묻는 관련 출력이 생성되었으며, 그 시점에서 나는 괜찮다고 결정했습니다. 나에게 도움이 된 VM을 망치기 전에 질문을 게시하는 것이 좋습니다. 잘 하셨습니다:

./secondpart.sh: line 8: filenames.txt: command not found
stat: missing operand
Try 'stat --help' for more information.
rm: missing operand
Try 'rm --help' for more information.
./secondpart.sh: line 8: file-roller.txt: command not found
stat: missing operand
Try 'stat --help' for more information.
rm: missing operand
Try 'rm --help' for more information./code>
./secondpart.sh: line 8: filesizes.txt: command not found
stat: missing operand
Try 'stat --help' for more information.
rm: missing operand
Try 'rm --help' for more information.
./secondpart.sh: line 8: file.txt: command not found
stat: missing operand
Try 'stat --help' for more information.
rm: cannot remove adammvirtual/Win10UbuntuVM001_apt_sources_file.txt':
 No such file or directory
rm: cannot remove '/home/adamvirtual/mapfile.txt': No such file or directory
rm: remove write-protected regular file '/usr/share/doc/alsa-base/driver/Procfile.txt.gz'?

프롬프트를 벗어나려면 ctrl+를 누릅니다 .C

답변1

문제는 ./secondpart.sh: line 8어느 것을 설정해야 하는가 입니다 $filename.

stat그리고 논쟁이 rm있어서 그들은 불평을 했습니다. $filename이러한 오류는 후속 오류입니다.

따라서 8행을 수정해야 합니다.

후속 오류를 방지하려면 거의 항상 set -euo pipefail첫 번째 오류 시 스크립트를 종료하여 스크립트를 시작해야 합니다.


그러나 전반적으로 스크립트가 너무 복잡하여 wc루프를 사용하므로 올바른 접근 방식이 아닙니다 for.sed파일을 한 줄씩 읽기.

파일 크기가 0인지 확인하는 데 사용하는 대신 stat -c %s다음을 사용할 수 있습니다.파일 테스트 연산자 -s, 정확히 그렇게 합니다(실제로 파일 크기가 다음과 같은 경우 반대의 경우를 확인합니다).아니요영).

예를 들면 다음과 같습니다.

xargs -a filenames.txt -I{} sh -c '[ -s "$1" ] || rm -i "$1"' xargs-sh {}

또는

readarray filenames < filenames.txt
for filename in "${filenames[@]}"; do
    [ -s "$filename" ] || rm -i "$filename"
done

또는

while IFS= read -r filename; do
    [ -s "$filename" ] || rm -i "$filename"
done < filenames.txt

일반적으로 파일 이름에 줄 바꿈이 허용되므로 텍스트 파일에서 파일 이름을 한 줄씩 표시하는 것은 좋지 않습니다. 대신 \0파일 구분 기호로 항상 널 문자( )를 사용해야 합니다 .

관련 정보