파이프를 통해 입력을 허용하는 명령의 Linux 구현과 명령 매개변수를 통해 입력을 허용하는 명령의 차이점은 무엇입니까?

파이프를 통해 입력을 허용하는 명령의 Linux 구현과 명령 매개변수를 통해 입력을 허용하는 명령의 차이점은 무엇입니까?

비슷한 질문이 많지만 내 질문에 직접적으로 답하는 질문을 찾을 수 없습니다. 운영체제 메모리 관리, 프로세스, 프로세스 간 통신 등의 기본을 이해합니다. 그러나 파이프를 통해 입력을 받을 수 있는 명령 구현과 명령 매개변수만 허용할 수 있는 명령 구현 간의 근본적인 차이점은 분명하지 않습니다.

명령이 한 가지 방법을 통한 입력은 허용하지만 다른 방법으로는 입력을 허용하지 않는 이유는 무엇이며, 명령이 허용하는 입력 방법을 어떻게 쉽게 알 수 있습니까?

ls간단한 예를 들자면, 출력의 파일 이름을 cat표시용으로 파이프할 수 있지만 에 대해서는 동일한 작업을 수행할 수 없는 이유는 무엇입니까 rm? 이러한 동작의 차이를 초래하는 철학적 이유, 심오한 기술적 이유 또는 구현 시 임의의 선택이 있습니까?

ls | cat
delete_me_1.txt
delete_me_2.txt

ls | rm
rm: missing operand

즉, Linux 명령을 작성하는 경우 파이프, 명령 매개변수 또는 둘 다를 통해 명령 입력을 허용할지 여부를 선택하기 위해 어떤 기술적 요소를 고려해야 합니까?

답변1

그러나 파이프를 통해 입력을 받을 수 있는 명령 구현과 명령 매개 변수만 허용할 수 있는 명령 구현 간의 근본적인 차이점은 분명하지 않습니다.

글쎄, 그 중 하나(또는 둘 다?)를 사용할지는 프로그램 개발자가 결정하는 문제입니다. 운영 체제와는 아무런 관련이 없으며 단지 운영 체제가 인수 전달, 입력 파일 설명자 읽기 및 읽기 메서드를 제공한다는 것뿐입니다. 표준 입력 렌더링 .

따라서 이 질문은 Linux보다 20년 이상 앞선 것입니다. 이는 표준 입력 및 명령줄 인수 개념이 최초로 등장한 시기입니다(Thompson, Ritchie, Kernigan 및 McIlroy가 등장하지 않았을 것으로 확신하는 UNIX의 탄생). 뜻밖에도).

즉, Linux 명령을 작성하는 경우 파이프, 명령 매개변수 또는 둘 다를 통해 명령 입력을 허용할지 여부를 선택하기 위해 어떤 기술적 요소를 고려해야 합니까?

귀하의 목적에 맞는 가용성과 적합성!

일부 데이터를 처리하면 더 많을 수도 있습니다.효과가있다특히 입력을 생성한 프로그램이 종료되기 전에 출력을 생성할 수 있는 경우 표준 입력으로 제공합니다. 프로그램 시작 시에만 명령줄 인수를 전달할 수 있으므로 연속 생산자를 사용하여 데이터 스트리밍이 필요한 작업을 수행하는 경우 이를 수행하는 방법을 궁금해할 필요가 없습니다.

무언가의 동작을 변경하거나 가변 개수의 인수를 기반으로 무언가를 계산하려는 경우 해당 인수를 입력으로 전달하는 구조화된 방법보다 명령줄 인수를 사용하는 것이 더 쉬울 수 있습니다.

그래서 그것은 실제로 당신이 어떻게 하느냐에 달려 있습니다.생각하다사용하고 싶은 프로그램. 기술적인 문제가 아니라 질문입니다.목적.

사실: 지금은 2022년입니다. 널리 사용되는 현대 언어의 경우 구조화된 입력 데이터(예: JSON)를 프로그램에서 쉽게 사용할 수 있는 사전/맵/키-값 데이터 구조로 구문 분석할 수 있는 라이브러리가 있습니다. 명령줄 인수를 구문 분석하는 경우에도 마찬가지입니다! 일반적으로 명령줄 인수 구문 분석기는 구성 파일도 구문 분석할 수 있으므로(CLI11과 같이 표준 입력을 구성 파일로 사용할 수 있음) 기술적으로 둘 중 하나를 수행할 수 있는 프로그램을 선택할 필요조차 없습니다.

답변2

명령이 한 가지 방법을 통한 입력을 허용하지만 다른 방법을 통한 입력은 허용하지 않는 이유는 무엇입니까?

결국 프로그램은 그렇게 만들어지기 때문이다.

보다 실질적으로, 프로그램은 가장 합리적인 방식으로 입력을 받아들이는 경향이 있습니다. 입력이 프로그램의 동작을 수정하는 파일 이름이나 옵션 세트인 경우 이는 일반적으로 명령줄에 제공됩니다. 일반적으로 이는 텍스트이며 짧습니다. 입력이 데이터 덩어리인 경우 stdin을 통해 읽습니다. 처리할 데이터는 바이너리 데이터일 수 있으며 길이가 길 수 있습니다.

예를 들어, 둘 다 명령줄 인수로 파일 이름 목록을 cat사용합니다 (둘 다 옵션을 사용할 수 있음). 또한 명령줄에서 파일 이름을 허용하지만 옵션도 허용하며, 그 중 일부는 해당 파일의 데이터에 적용되는 실제 지침을 지정할 수 있습니다. 그것들은 모두 지정된 파일에 대해 작동합니다. 내용을 인쇄하고, 삭제하고, 지정된 방식으로 내용을 처리합니다.rmsedcatrmsed

파일 이름이 지정되지 않으면 둘 다 sed기본적으로 표준 입력을 읽습니다.cat

명령이 허용하는 입력 방법을 어떻게 쉽게 알 수 있습니까?

당신은 설명서를 읽었습니다. 아니면 합리적인 상황을 바탕으로 추측해 보세요.

ls간단한 예를 들자면, 출력의 파일 이름을 cat표시용으로 파이프할 수 있지만 에 대해서는 동일한 작업을 수행할 수 없는 이유는 무엇입니까 rm?

cat기본적으로 데이터 스트림은 표준 입력에서 가져오기 때문에 rm파일 이름 목록만 가져옵니다. 참고로 ls | cat이렇게 하면아니요 cat나열된 파일 이름에 대해 작동하지만목록 자체. ls인쇄해서 출력 해도 foo.txt출력 이 됩니다ls |catfoo.txtcat foo.txt콘텐츠foo.txt. ls * |cat와 같지 않습니다 cat *.

이제 옵션 없이 일반 파이프를 통과하는 것은 cat데이터를 있는 그대로 전달하기 때문에 약간 쓸모가 없습니다. 사용하는 것이 더 합리적일 수 있습니다 cat -n.

예, 출력은 ls기본적으로 텍스트 파일과 마찬가지로 데이터 스트림입니다. 사람의 눈에는 파일 이름 목록처럼 보일 수 있지만 실제로는 매우 어렵습니다.적절하게사람들이 다음과 같은 기사를 쓰는 방식으로 사용하십시오.https://mywiki.wooledge.org/ParsingLs그것에 반대하기 위해. 이 기사는 여러 차례 여기에 연결되어 있었는데, 이는 매우 흔한 오해입니다. (예, 물론 xargs데이터 스트림을 명령줄 인수 목록으로 변환하는 유사한 도구가 있습니다. 하지만 음... 파일 이름에 줄 바꿈이 유효하다는 점만 기억하세요.)

이러한 동작의 차이를 초래하는 철학적 이유, 심오한 기술적 이유 또는 구현 시 임의의 선택이 있습니까?

아름다움은 보는 사람의 눈에 달려 있는 것처럼 들리지만 FWIW, 나는 실제 기술적인 이유만 봅니다(위 참조).

(*기타 경우: 명령줄 옵션( )을 통해 이름이 지정된 sed파일의 명령을 처리할 수도 있습니다 -f. 이는 C 프로그램을 파일에 저장하는 것처럼 스크립트가 긴 경우에 적합합니다. 일부 프로그램은 구성 파일을 읽습니다. 일부 사람들이 선택하는 명령줄 옵션도 의미가 있습니다. 왜냐하면 사용자는 마법 단어 세트만 학습하면 되고 파일은 영구 저장에 더 적합하기 때문입니다.

답변3

목재를 절단하는 기계를 설계하는 경우 입력된 수량은 목재라고 생각하고 절단 두께와 같은 매개변수는 작업 기간 동안 설정됩니다.

많은 데이터 작업이 이러한 비유와 관련되어 있습니다. 체인 연결(파이핑), 병렬화, 배포 등 다양한 배열 및 아키텍처와 함께 작동합니다. 이 패러다임은 매우 유연하고 강력합니다.

wood > board 15cm | style moulding | transport | varnishing | transport > deposit

그래서 질문은"무엇"그리고"어떤 방식으로"먼저 답변을 얻으세요. 작업이 임의적으로 많은 양의 데이터를 처리할 수 있는 경우 이는 입력이어야 하며 다른 정보는 설정 또는 매개변수입니다.

잘 설계된 프로그램은 필터입니다. 즉, 단순히 파이프를 통해 협력합니다. 매우 일반적인 프로그램 sed, grep, awk, gzip, cat, md5sum, base64, bash, ssh등이 표준 입력을 읽도록 설계되었음을 알 수 있습니다 . 또는 데이터 자체가 아닌 데이터 소스인 파일 이름을 인수로 허용합니다. 파일 이름은 메타데이터이고 내용은 데이터입니다.

md5sum < /etc/crontab # don't care metadata
md5sum /etc/crontab # same result with metadata

rm모호합니다. 항목을 허용하면 제거할 경로가 될 수 있지만 매개변수로 유지하는 것이 더 편리해 보입니다.

어쨌든 입력 스트림에서 매개변수로 전환하는 방법에는 여러 가지가 있습니다. 입력을 매개변수로 변환할 때 인터프리터 제한 사항 및 기타 구문 분석 함정(따옴표, 구분 기호, 대체)을 고려해야 합니다.

ls | xargs -d'\n' rm # apply rm according to arg length limits
         # NOT broken by spaces in filenames
         # broken by newlines in filenames

ls | parallel -m rm # apply rm whith many parallel processes
         # NOT broken by spaces in filenames
         # broken by newlines in filenames

ls | while read;do rm "$REPLY";done # apply rm one by one
         # NOT broken by spaces in filenames
         # broken by newlines in filenames

ls | split -l1 --filter='read && rm "$REPLY"'
         # why make it simple when you can make it complicated

rm $(ls) # apply rm all at once
         # broken by arg length limit
         # broken by space in filenames

rm * # apply rm all at once
     # broken by arg length limit
     # NOT broken by newline in filenames

(결론: 문제가 발생하면 파일 이름에 줄바꿈을 추가하세요)

때로는 비즈니스 데이터로 작업할 때 처리할 데이터 유형이나 기타 메타데이터와 같이 데이터를 특징짓는 일부 정보를 매개변수에 입력하는 경향이 있습니다. 메타데이터와 다른 매개변수를 구별하는 것이 좋은 생각이라고 생각합니다. 기계가 메타데이터를 읽고 적응할 수 있는 한 메타데이터는 데이터와 함께 자연스럽게 발생합니다.

예:

hard wood > board 15cm | style moulding | transport | varnishing | transport > deposit

이 경우 작업자가 조정 사항을 확인하도록 하는 대신 절단기와 셰이퍼가 출력과 블레이드를 조정할 수 있다면 이점을 얻을 수 있습니다.

단일 데이터 스트림을 구축하기 위해 일부 메타데이터와 데이터를 결합하는 많은 프로그램 예제가 있습니다.

tar -cf- /etc | tar -tf-

마지막으로, 광범위하게 분산된 비즈니스 워크플로우에서는 특히 추적성이 필요하기 때문에 특정 작업(예: 로컬 매개변수)에만 관련된 정보와 입력, 데이터 및 메타데이터를 따르는 정보를 명확하게 구분해야 합니다.

한 가지 더 알아야 할 사항: 매개변수는 명령에 공개적으로 표시되므로 ps비밀 매개변수로 프로그램을 설계하는 것은 매우 나쁜 생각입니다. 대신 간접 입력 방법을 사용하세요.

관련 정보