
나는 다양한 명령을 다른 기호와 연결하는 온라인 튜토리얼을 자주 봅니다. 예를 들어:
command1 | command2
command1 & command2
command1 || command2
command1 && command2
다른 사람들은 명령을 파일에 연결하는 것 같습니다.
command1 > file1
command1 >> file1
이것들은 무엇입니까? 이름은 무엇입니까? 걔들 뭐해? 더 있나요?
답변1
이를 쉘 연산자라고 하며 예, 더 많은 것이 있습니다. 두 가지 주요 클래스 중 가장 일반적인 클래스에 대해 간략하게 설명하겠습니다.제어 연산자그리고리디렉션 연산자, 그리고 bash 쉘과 관련하여 작동하는 방식.
A. 제어 연산자
쉘 명령 언어에서 제어 기능을 수행하는 토큰.
다음 기호 중 하나입니다.
& && ( ) ; ;; <newline> | ||
그리고 |&
배쉬에서.
A !
는~ 아니다제어 연산자이지만예약어. 내부에서는 논리적 NOT [부정 연산자]가 됩니다.산술 표현식및 내부 테스트 구성(여전히 공백 구분 기호가 필요함).
A.1 목록 종결자
;
: 첫 번째 결과에 관계없이 다른 명령이 완료된 후 하나의 명령을 실행합니다.command1 ; command2
첫 번째 command1
는 전경에서 실행되고, 완료되면 command2
실행됩니다.
문자열 리터럴에 없거나 특정 키워드 뒤에 있는 개행 문자는 다음과 같습니다.~ 아니다세미콜론 연산자와 동일합니다. 구분된 단순 명령 목록 ;
은 여전히목록- 쉘의 파서는 실행하기 전에 구분된 단순 명령 뒤에 오는 단순 명령을 계속해서 읽어야 하는 ;
반면, 개행 문자는 전체 명령 목록 또는 목록 목록을 구분할 수 있습니다. 차이점은 미묘하지만 복잡합니다. 쉘이 개행 다음에 오는 데이터를 읽어야 하는 이전 명령이 없었을 때 개행은 쉘이 이미 읽은 간단한 명령을 평가하기 시작할 수 있는 지점을 표시하는 반면 세미콜론은 ;
수행합니다. 아니다.
&
: 백그라운드에서 명령이 실행되어 동일한 셸에서 계속 작업할 수 있습니다.command1 & command2
여기서는 command1
백그라운드에서 실행되어 종료를 command2
기다리지 않고 즉시 포그라운드에서 실행을 시작합니다 .command1
뒤의 개행 문자 command1
는 선택 사항입니다.
A.2 논리 연산자
&&
: AND 목록을 작성하는 데 사용되며 다른 명령이 성공적으로 종료된 경우에만 하나의 명령을 실행할 수 있습니다.command1 && command2
여기서는 완료된 command2
후에 실행됩니다 .command1
오직성공한 경우 command1
(종료 코드가 0인 경우) 두 명령 모두 포그라운드에서 실행됩니다.
이 명령은 다음과 같이 작성할 수도 있습니다.
if command1
then command2
else false
fi
또는 단순히 if command1; then command2; fi
반환 상태가 무시되는 경우입니다.
||
: OR 목록을 작성하는 데 사용되며 다른 명령이 성공적으로 종료되지 않은 경우에만 하나의 명령을 실행할 수 있습니다.command1 || command2
여기서는 실패한 command2
경우에만 실행됩니다 command1
(0이 아닌 종료 상태를 반환한 경우). 두 명령 모두 포그라운드에서 실행됩니다.
이 명령은 다음과 같이 작성할 수도 있습니다.
if command1
then true
else command2
fi
또는 더 짧은 방법으로 if ! command1; then command2; fi
.
&&
과 는 ||
왼쪽 연관적이라는 점에 유의하세요 . 보다쉘 논리 연산자 &&, ||의 우선순위자세한 내용은.
!
: 이것은 명령의 반환 상태를 부정하는 데 사용되는 "not" 연산자(단 구분 기호가 있어야 함) 역할을 하는 예약어입니다. 명령이 0이 아닌 상태를 반환하면 0을 반환하고, 상태 0을 반환하면 1을 반환합니다. . 또한 유틸리티에 대한 논리적 NOT입니다test
.! command1 [ ! a = a ]
그리고 산술 표현식 내의 실제 NOT 연산자:
$ echo $((!0)) $((!23))
1 0
A.3 파이프 운영자
|
: 파이프 연산자는 한 명령의 출력을 다른 명령의 입력으로 전달합니다. 파이프 연산자로 작성된 명령을관로.command1 | command2
에 의해 인쇄된 모든 출력은
command1
에 입력으로 전달됩니다command2
.|&
2>&1 |
: 이것은 bash 및 zsh 의 약어입니다 . 한 명령의 표준 출력과 표준 오류를 다른 명령의 입력으로 전달합니다.command1 |& command2
A.4 기타 목록 구두점
;;
끝을 표시하는 데에만 사용됩니다.사례 진술. Ksh, bash 및 zsh는 또한 ;&
다음 사례로 넘어갈 수 있도록 지원하며 ;;&
(ATT ksh에서는 아님) 계속해서 후속 사례를 테스트합니다.
(
그리고 )
익숙하다그룹 명령서브셸에서 실행합니다. {
또한 }
명령을 그룹화하지만 하위 쉘에서 실행하지 마십시오. 보다이 답변쉘 구문의 다양한 유형의 괄호, 대괄호 및 중괄호에 대한 설명입니다.
B. 리디렉션 연산자
쉘 명령 언어에서 리디렉션 기능을 수행하는 토큰입니다. 다음 기호 중 하나입니다.
< > >| << >> <& >& <<- <>
이를 통해 명령의 입력과 출력을 제어할 수 있습니다. 이는 간단한 명령 내의 어느 위치에나 나타나거나 명령을 따를 수 있습니다. 리디렉션은 나타나는 순서대로 왼쪽에서 오른쪽으로 처리됩니다.
<
: 명령에 대한 입력을 제공합니다.command < file.txt
위의 command
내용은 의 내용에 대해 실행됩니다 file.txt
.
<>
: 위와 동일하지만 파일이 다음 위치에 열려 있습니다.읽기+쓰기대신 모드읽기 전용:command <> file.txt
파일이 존재하지 않으면 생성됩니다.
해당 연산자는 거의 사용되지 않습니다. 왜냐하면 명령은 일반적으로읽다하지만 표준 입력에서여러 가지 특정 상황에서 유용할 수 있습니다..
>
: 명령의 출력을 파일로 지정합니다.command > out.txt
위의 출력 command
은 out.txt
. 파일이 존재하면 해당 내용을 덮어쓰고, 존재하지 않으면 생성됩니다.
이 연산자는 또한 무엇인가를 인쇄할지 여부를 선택하는 데 자주 사용됩니다.표준 에러또는표준 출력:
command >out.txt 2>error.txt
위의 예에서 >
표준 출력을 리디렉션하고 2>
표준 오류를 리디렉션합니다. 를 사용하여 출력을 리디렉션할 수도 있지만 1>
이것이 기본값이므로 1
일반적으로 는 생략되고 간단히 로 작성됩니다 >
.
따라서 실행 command
하고 file.txt
출력을 저장하려면 out.txt
다음과 같은 오류 메시지가 error.txt
실행됩니다.
command < file.txt > out.txt 2> error.txt
>|
: 와 동일>
하지만 쉘이 덮어쓰기를 거부하도록 구성되었더라도( 또는 사용set -C
) 대상을 덮어씁니다set -o noclobber
.command >| out.txt
존재하는 경우 out.txt
의 출력이 command
해당 콘텐츠를 대체합니다. 존재하지 않는 경우 생성됩니다.
>>
>
: 대상 파일이 존재하는 경우 새 데이터가 추가된다는 점을 제외하면 와 동일합니다 .command >> out.txt
존재하는 경우 out.txt
의 출력은 command
이미 포함된 항목 뒤에 추가됩니다. 존재하지 않는 경우 생성됩니다.
>&
: (POSIX 사양에 따라) 다음으로 둘러싸여 있을 때숫자(1>&2
) 또는-
오른쪽 (1>&-
) 중 하나는 리디렉션만하나파일 설명자를 닫거나 닫습니다(>&-
).
>&
파일 설명자 번호 뒤에 오는 것은 파일 설명자를 리디렉션하는 이식 가능한 방법이며 파일 >&-
설명자를 닫는 이식 가능한 방법입니다.
이 리디렉션의 오른쪽이 파일인 경우 다음 항목을 읽어보세요.
>&
,&>
, : (위에서도 읽어>>&
보세요&>>
) 표준 오류와 표준 출력을 각각 바꾸거나 추가하여 리디렉션합니다.command &> out.txt
의 표준 오류와 표준 출력은 모두 command
에 저장되며 out.txt
내용을 덮어쓰거나 내용이 없으면 새로 생성됩니다.
command &>> out.txt
위와 동일하지만 out.txt
존재하는 경우 출력 및 오류가 command
추가됩니다.
변형 &>
은 에서 발생 bash
하고 >&
변형은 csh(수십 년 전)에서 발생합니다. 둘 다 다른 POSIX 셸 연산자와 충돌하므로 이식 가능한 sh
스크립트에 사용하면 안 됩니다.
<<
: 여기 문서입니다. 여러 줄의 문자열을 인쇄하는 데 자주 사용됩니다.command << WORD Text WORD
여기서는 위의 예에서 입력으로 다음
command
항목을 찾을 때까지 모든 것을 가져옵니다 . 종종 또는 그 변형이기는 하지만 원하는 영숫자(뿐만 아니라) 문자열일 수도 있습니다. 의 일부가 인용되거나 이스케이프되면 여기 문서의 텍스트가 문자 그대로 처리되며 확장이 수행되지 않습니다(예: 변수). 따옴표가 없으면 변수가 확장됩니다. 자세한 내용은 다음을 참조하세요.WORD
Text
WORD
EoF
WORD
배쉬 매뉴얼.command << WORD ... WORD
의 출력을 다른 명령으로 직접 파이프하려면 파이프를 와 같은 줄에 배치해야 하며<< WORD
종료 WORD 뒤나 다음 줄에 파이프를 배치할 수 없습니다. 예를 들어:command << WORD | command2 | command3... Text WORD
<<<
: Here 문자열은 here 문서와 유사하지만 단일 행용입니다. 이는 Unix 포트 또는 rc(원래 위치), zsh, ksh의 일부 구현, yash 및 bash에만 존재합니다.command <<< WORD
로 주어진 것은 무엇이든 WORD
확장되고 그 값은 에 입력으로 전달됩니다 command
. 이는 변수의 내용을 명령에 대한 입력으로 전달하는 데 자주 사용됩니다. 예를 들어:
$ foo="bar"
$ sed 's/a/A/' <<< "$foo"
bAr
# as a short-cut for the standard:
$ printf '%s\n' "$foo" | sed 's/a/A/'
bAr
# or
sed 's/a/A/' << EOF
$foo
EOF
몇 가지 다른 연산자( >&-
, x>&y
x<&y
)를 사용하여 파일 설명자를 닫거나 복제할 수 있습니다. 이에 대한 자세한 내용은 쉘 설명서의 관련 섹션(여기예를 들어 bash의 경우).
이는 Bourne과 같은 쉘의 가장 일반적인 연산자만 다룹니다. 일부 셸에는 몇 가지 추가 리디렉션 연산자가 있습니다.
Ksh, bash 및 zsh에도 <(…)
, >(…)
및 구문이 있습니다 =(…)
(후자의 구문 zsh
만 해당). 리디렉션은 아니지만프로세스 대체.
답변2
'>' 관련 경고
<
I/O 리디렉션( 및 ) 에 대해 방금 배운 Unix 초보자는 >
종종 다음과 같은 것을 시도합니다.
명령…입력 파일>the_same_file
또는
명령… <파일 >the_same_file
또는 거의 동등하게,
고양이파일|명령… >the_same_file
( grep
, sed
, cut
, sort
및 는 spell
사람들이 이와 같은 구성에서 사용하고 싶은 명령의 예입니다.) 사용자는 이러한 시나리오로 인해 파일이 비어 있다는 사실에 놀랐습니다.
다른 답변에서는 언급되지 않은 듯한 뉘앙스가 첫문장에 숨어있습니다.리디렉션섹션배쉬(1):
명령이 실행되기 전에 명령의 입력과 출력이 변경될 수 있습니다.리디렉션됨 쉘에서 해석되는 특수 표기법을 사용합니다.
처음 5개 단어는 셸이 요청된 리디렉션을 수행한다는 사실을 강조하기 위해 굵게, 기울임꼴, 밑줄, 확대, 깜박임, 빨간색으로 표시하고 아이콘으로 표시해야 합니다.명령이 실행되기 전에. 그리고 또한 기억하세요
출력을 리디렉션하면 파일이 ... 쓰기 위해 열립니다 .... 파일이 존재하지 않으면 생성됩니다. 존재하는 경우 크기가 0으로 잘립니다.
따라서 이 예에서는 다음과 같습니다.
sort roster > roster
쉘은 프로그램 실행이 시작
roster
되기 전에 쓰기 위해 파일을 열고 파일을 잘라냅니다(즉, 모든 내용을 삭제합니다) .sort
당연히 데이터를 복구하기 위해 아무 것도 할 수 없습니다.순진하게도 그렇게 기대할 수도 있다.
tr "[:upper:]" "[:lower:]" < poem > poem
더 나을 수도 있습니다. 쉘은 왼쪽에서 오른쪽으로의 방향 재지정을 처리하기 때문에 쓰기(표준 출력)를 위해 열기 전에
poem
읽기( 의 표준 입력)를 위해 열립니다.tr
하지만 그것은 도움이 되지 않습니다. 이 일련의 작업으로 인해 두 개의 파일 핸들이 생성되더라도 둘 다 동일한 파일을 가리킵니다. 쉘이 읽기 위해 파일을 열면 내용은 그대로 남아 있지만 프로그램이 실행되기 전에 여전히 손상됩니다.
그렇다면 어떻게 해야 할까요?
솔루션에는 다음이 포함됩니다.
실행 중인 프로그램에 출력 위치를 지정하는 자체 내부 기능이 있는지 확인하세요. 이는 종종
-o
(또는--output=
) 토큰으로 표시됩니다. 특히,sort -o roster roster
대략 동일하다
sort roster > roster
단, 첫 번째 경우에는
sort
프로그램이 출력 파일을 엽니다. 그리고 출력 파일을 열 때까지 열지 않는 것은 충분히 똑똑합니다.~ 후에모든 입력 파일을 읽었습니다.마찬가지로, 적어도 일부 버전에는 (
sed
편집-i
나n 자리) 출력을 입력 파일에 다시 쓰는 데 사용할 수 있는 옵션입니다(다시 말하지만,~ 후에모든 입력을 읽었습니다).ed
/ex
,emacs
,pico
및vi
/ 와 같은 편집기를 사용하면vim
사용자가 텍스트 파일을 편집하고 편집된 텍스트를 원본 파일에 저장할 수 있습니다.ed
(적어도) 비대화형 으로 사용할 수 있습니다.vi
관련 기능이 있습니다. 를 입력하면 편집 버퍼의 내용이 다음 위치에 기록됩니다.:%!command
Entercommand
, 출력을 읽고 이를 버퍼에 삽입합니다(원본 내용 대체).
간단하지만 효과적인:
명령…입력 파일>임시_파일 && MV임시_파일 입력 파일
여기에는 단점이 있습니다.
input_file
링크이므로 (아마도) 별도의 파일로 대체될 것입니다. 또한 새 파일은 기본 보호 기능을 통해 귀하의 소유가 됩니다. 특히 이는 원본 파일이 있더라도 파일을 누구나 읽을 수 있게 될 위험이 있습니다.input_file
그렇지 않았습니다.변형:
command … input_file > temp_file && cp temp_file input_file && rm temp_file
여전히 (잠재적으로) 떠날 것입니다temp_file
세계적으로 읽을 수 있습니다. 더 나은 점:cp input_file temp_file && command … temp_file > input_file && rm temp_file
이는 파일의 링크 상태, 소유자 및 모드(보호)를 유지하지만 잠재적으로 I/O 비용이 두 배 더 커집니다. ( 속성을 보존하려면-a
또는-p
on 과 같은 옵션을 사용해야 할 수도 있습니다 .)cp
command … input_file > temp_file &&
cp --attributes-only --preserve=all input_file temp_file &&
mv temp_file input_file
(가독성을 위해 별도의 줄로 구분) 이는 파일의 모드(루트인 경우 소유자)를 유지하지만 해당 파일을 사용자가 소유하게 하고(루트가 아닌 경우) 새 파일로 만듭니다. 별도의 파일.
이 블로그 (파일의 "내부" 편집)을 제안하고 설명합니다.
{ rm입력 파일 && 명령… >입력 파일; } <입력 파일
이를 위해서는
command
표준 입력을 처리할 수 있습니다(그러나 거의 모든 필터는 처리 가능). 블로그 자체에서는 이를 위험한 클러지라고 부르며 사용을 권장하지 않습니다. 그리고 이렇게 하면 귀하가 소유하고 기본 권한을 가진 별도의 새 파일(아무것에도 연결되지 않음)이 생성됩니다.moreutils 패키지에는 다음 명령이 있습니다
sponge
.명령…입력 파일| 스펀지the_same_file
보다이 답변자세한 내용은.
나에게 완전히 놀라운 사실은 다음과 같습니다. 구문 오류가 말합니다:
[대부분의 솔루션]은 읽기 전용 파일 시스템에서 실패합니다. 여기서 "읽기 전용"은
$HOME
~ 할 것이다쓸/tmp
수 있지만읽기 전용(기본적으로). 예를 들어, Ubuntu가 있고 복구 콘솔로 부팅한 경우 이는 일반적으로 그렇습니다. 또한 here-document 연산자<<<
도 작동하지 않습니다/tmp
.읽기/쓰기 거기에 임시 파일도 쓰기 때문입니다.
(참조.이 질문'd 출력 포함strace
)
이 경우 다음이 작동할 수 있습니다.
- 고급 사용자에게만 해당:
명령이 입력과 동일한 양의 출력 데이터를 생성하도록 보장되는 경우(예:
sort
또는tr
없이또는 옵션) 시도해 볼 수 있습니다-d
.-s
명령…입력 파일| dd =the_same_file전환=notrunc
보다이 답변 그리고이 답변위에 대한 설명과 명령이 입력과 동일한 양의 출력 데이터를 생성하도록 보장되는 경우 작동하는 대안을 포함한 자세한 내용이하(예:grep
, 또는cut
). 이러한 답변은 여유 공간이 필요하지 않거나 거의 필요하지 않다는 장점이 있습니다. 위 양식의 답변에서는 시스템이 전체 입력(이전) 파일과 출력(새) 파일을 동시에 보관할 수 있을 만큼 충분한 여유 공간이 있어야 함을 분명히 요구합니다. 이는 대부분의 다른 솔루션(예: 및 )에서도 마찬가지입니다 . 예외: 출력을 쓰기 전에 모든 입력을 읽어야 하고 아마도 해당 데이터의 전부는 아니더라도 대부분을 임시 파일에 버퍼링하기 때문에 많은 여유 공간이 필요할 것입니다 .command … input_file > temp_file && …
sed -i
sponge
sort … | dd …
sort
- 고급 사용자에게만 해당:
명령…입력 파일1<>the_same_file
위의 답변 과 동일할 수 있습니다dd
. 구문 은 파일 설명자에서 명명된 파일을 엽니다.n<> file
n
입력과 출력 모두에 대해, 자르지 않고 – 일종의 조합 과 . 참고: 일부 프로그램(예: 및 )은 입력과 출력이 동일한 파일임을 감지할 수 있기 때문에 이 시나리오에서 실행을 거부할 수 있습니다. 보다n<
n>
cat
grep
이 답변 위의 내용에 대한 논의와 명령이 입력과 동일한 양의 출력 데이터를 생성하도록 보장되는 경우 이 답변이 작동하도록 하는 스크립트이하.
경고: 나는 Peter의 스크립트를 테스트하지 않았으므로 이를 보증하지 않습니다.
그렇다면 질문은 무엇이었나요?
이것은 U&L에서 인기 있는 주제였습니다. 이는 다음 질문에서 해결됩니다.
- 파일을 내부에서 수정하는 방법이 있나요?
iconv
입력 파일을 변환된 출력으로 바꾸려면 어떻게 해야 합니까 ?- 명령이
shuf file > file
빈 파일을 남기는 이유는 무엇입니까? - 덮어쓰지 않고 Linux에서 동일한 파일을 읽고 쓸 수 있습니까?
- 명령어로 처리된 소스 파일과 동일한 파일로 리다이렉트
- 이
sort
명령이 빈 파일을 제공하는 이유는 무엇입니까? tr
stdout을 파일로 리디렉션- grep: 입력 파일 'X'도 출력입니다.
- 리디렉션 연산자는 파일 설명자를 병렬로 열 수 있나요?
- 리디렉션은 파일을 덮어쓰지 않고 빈 파일만 생성합니다.
… 그리고 그것은 슈퍼유저나 Ask Ubuntu를 포함하지 않습니다. 위 질문에 대한 답변의 많은 정보를 이 답변에 포함했지만 전부는 아닙니다. (즉, 자세한 내용은 위에 나열된 질문과 답변을 읽어보세요.)
추신 : 나는아니요위에 언급한 블로그와 제휴 관계를 맺고 있습니다.
답변3
;
, &
및 (
에 대한 추가 관찰)
terdon의 답변에 있는 일부 명령은 null일 수 있습니다. 예를 들어 다음과 같이 말할 수 있습니다.
command1 ;
(없음
command2
). 이는 다음과 같습니다.command1
(즉, 단순히
command1
포그라운드에서 실행되고 완료될 때까지 기다립니다. 이에 비해,command1 &
(없음
command2
)은command1
백그라운드에서 실행된 다음 즉시 다른 쉘 프롬프트를 발행합니다.그에 비해 ,
command1 &&
,command1 ||
는command1 |
의미가 없습니다. 이들 중 하나를 입력하면 쉘은 (아마도) 명령이 다른 행에 계속된다고 가정합니다. 일반적으로 로 설정되는 보조(계속) 쉘 프롬프트가 표시되고>
계속해서 읽혀집니다. 쉘 스크립트에서는 다음 줄을 읽고 이미 읽은 줄에 추가합니다. (주의: 이것은 당신이 원하는 일이 아닐 수도 있습니다.)참고: 일부 쉘의 일부 버전에서는 이러한 불완전한 명령을 오류로 처리할 수 있습니다. 그러한 경우(또는 실제로는어느긴 명령이 있는 경우)
\
줄 끝에 백슬래시( )를 넣어 쉘이 다른 줄에서 명령을 계속 읽도록 지시할 수 있습니다.command1 && \ command2
또는
find starting-directory -mindepth 3 -maxdepth 5 -iname "*.some_extension" -type f \ -newer some_existing_file -user fred -readable -print
terdon이 말했듯이
(
명령)
을 그룹화하는 데 사용할 수 있습니다. 그 논의와 "실제로 관련이 없다"는 진술은 논쟁의 여지가 있습니다. terdon의 답변에 포함된 명령 중 일부는 다음과 같을 수 있습니다.여러 떼. 예를 들어,( command1 ; command2 ) && ( command3; command4 )
다음을 수행합니다.
- 실행
command1
하고 완료될 때까지 기다립니다. - 그런 다음 첫 번째 명령 실행 결과에 관계없이 명령을 실행
command2
하고 완료될 때까지 기다립니다. 그러다가
command2
성공 하면- 실행
command3
하고 완료될 때까지 기다립니다. - 그런 다음 해당 명령 실행 결과에 관계없이 명령을 실행
command4
하고 완료될 때까지 기다립니다.
실패 하면
command2
명령줄 처리를 중지합니다.- 실행
- 실행
괄호 바깥쪽은
|
매우 단단하게 묶여 있으므로command1 | command2 || command3
는 다음과 같습니다
( command1 | command2 ) || command3
및 보다 더 단단히 바인딩
&&
하므로||
;
command1 && command2 ; command3
는 다음과 같습니다
( command1 && command2 ) ; command3
즉, 및/또는
command3
의 종료 상태에 관계없이 실행됩니다 .command1
command2