Bash는 이런 방식으로 다른 명령을 표준 입력으로 연결할 수 있습니다.
$ ls /bin/aud* | cat
/bin/audacity
/bin/audiocompose
/bin/audiosend
...
...그리고 이 방법으로:
$ cat <(ls /bin/aud*)
/bin/audacity
/bin/audiocompose
/bin/audiosend
...
그러나 동일한 패턴을 사용하여 SQLite에 쿼리를 보내려고 하면 첫 번째 양식에서 다음과 같은 결과가 나타납니다.
$ echo "select count(*) from urls;" | \
sqlite3 ~/.config/google-chrome/Default/History
5983
...하지만 두 번째 오류는 다음과 같습니다.
$ sqlite3 ~/.config/google-chrome/Default/History \
<(echo "select count(*) from urls;")
Error: near "/": syntax error
이것은 놀라운 일입니다... SQL 문은 쉘에 의해 삽입되거나 엉망이 되지 않습니다.
$ echo "select count(*) from urls;"
echo "select count(*) from urls;"
이는 둘 중 하나와 관련이 없습니다 echo
. 확실히 리디렉션에 사용될 수 있습니다.
$ cat <(echo Foo)
Foo
내가 생각할 수 있는 것은 데이터베이스 파일의 경로가 어떻게든 잘못 해석되어 SQL 문으로 전달되었다는 것입니다. ("/"가 포함된 유일한 장소입니다. "/ 근처의 구문 오류에 대한 유일한 설명입니다." .
그런데 왜? 어떤 아이디어가 있나요?
답변1
I/O 리디렉션의 두 번째 형식( <(cmd)
)은 cmd | other-cmd
첫 번째 형식( )과 다르게 동작합니다.
첫 번째는 의 출력을 cmd
의 입력에 연결 other-cmd
하지만 두 번째는 경로 /dev/fd
또는명명된 파이프명령의 경로입니다. 의 표준 출력은 해당 파이프의 다른 쪽 끝에 바인딩되지만 이는 표준 입력 또는 파일 경로에서 읽는 명령과 동일합니다 cmd
. 동작은 그런 방식이 아니므로 두 가지 형태의 I/O 리디렉션 간의 차이점을 드러냅니다.cat
sqlite3
sqlite3
예상하다데이터베이스 경로 뒤에는 선택적 SQL 문이 있으므로 이 대체 경로를 SQL로 구문 분석하려고 시도하지만 실패합니다.
그건 그렇고, 이는 I/O 리디렉션이 전혀 필요하지 않음을 의미합니다. 이 명령은 시도한 어떤 형식보다 원하는 작업을 더 효율적으로 수행합니다.
$ sqlite3 ~/.config/google-chrome/Default/History "select count(*) from urls"
sqlite3
단일 SQL 문을 명령줄 매개 변수로 전달할 때는 세미콜론으로 끝나는 문이 필요하지 않습니다.
답변2
$ echo <(echo "hi")
/dev/fd/63
/dev/fd/63
SQL이 아니므로 sqlite3
표시된 오류 메시지와 함께 실패합니다. cat
대조적으로, 파일 읽기(또는 표준 입력 읽기)에는 매우 좋습니다. 생성된 명명된 파이프 또는 /dev/fd
파일 <(list)
은 표준 입력이 아닙니다.