주어진 파일 F의 각 라인 L에 대해 특정 명령 C를 실행한 다음 실패한 각 L에 대해 C(L)를 이동하는 깔끔한 방법은 무엇입니까?

주어진 파일 F의 각 라인 L에 대해 특정 명령 C를 실행한 다음 실패한 각 L에 대해 C(L)를 이동하는 깔끔한 방법은 무엇입니까?

예를 들어

https://example.nosuchtld
https://example.net
https://example.org
https://example.willfail

응 내용 urls.txt. 모든 URL/라인에 대해 -where를 실행하고 싶습니다 <command> <url>.urls.txt<command>curl

cat urls.txt | xargs -n1 curl

또는

<urls.txt xargs -n1 curl

예를 들어. curl성공적으로 편집되지 않은 모든 URL/행을 원합니다 (첫 번째와 마지막).

  1. 삭제되었습니다 urls.txt.
  2. 다른 파일에 추가 - nope.txt이미 존재하지 않는 경우 생성

urls.txt다음 과 같이 떠나다

https://example.net
https://example.org

그리고nope.txt

https://example.nosuchtld
https://example.willfail

쉘에서 실행되는 각 명령의 종료 상태는 명령의 성공적인 실행을 나타내는 변수를 통해 사용할 수 있는 반면 다른 모든 정수는 실패를 나타냅니다 $?. 0그러나 이를 포함하고 읽고 있는 파일에서 줄을 제거하고 다른 파일에 추가하는 복합 명령을 작성하는 방법을 잘 모르겠습니다.

답변1

을 사용하면 bash반복하여 URL을 얻고 명령을 테스트할 수 있습니다 curl. --fail이 옵션은 curl스크립트 내에서 사용하는 것이 좋을 것 같습니다. 다음을 참조하세요. 컬과 같은 명령이 오류 없이 완료되었는지 확인하는 방법

따라서 다음과 같이 보일 수 있습니다.

while read -r url; do
    curl -f "$url" && outputfile='success.txt' || outputfile='nope.txt'
    printf "%s\n" "$url" >> "$outputfile"
done < urls.txt

성공적인 URL로 파일을 덮어씁니다.

mv success.txt urls.txt

또는 mapfile다음을 사용하여 행을 배열에 넣습니다.

mapfile -t urls < urls.txt

for url in "${urls[@]}"; do
    curl -f "$url" && outputfile='success.txt' || outputfile='nope.txt'
    printf "%s\n" "$url" >> "$outputfile"
done

URL에는 공백이 없습니다. 인수가 문자가 포함된 전체 줄인 명령을 실행해야 하는 경우 이 게시물은 각 줄을 읽는 방법에 유용합니다."IFS=read-r-line" 이해

답변2

zsh를 사용하면 다음을 수행할 수 있습니다.

while IFS= read -ru3 url; do
  curl -- $url
  print -ru $(( $? ? 4 : 5 )) -- $url
done 3< urls 4> bad 5> good

이런 방식으로 badgood파일은 한 번만 열리며 urls해당 파일 자체를 읽기 위해 열 수 있는 경우에만 열립니다.

관련 정보