파일이 있는 장치를 어떻게 찾고 스크립트에서 사용할 수 있나요?

파일이 있는 장치를 어떻게 찾고 스크립트에서 사용할 수 있나요?

내 파일이 어떤 장치에 있는지 확인하여 스크립트에서 사용할 수 있도록 하고 싶습니다. 나는 이것을 할 수 있다:

$ df  .
Filesystem   512-blocks      Used Available Capacity  Mounted on
/dev/disk0s2  498438976 294369520 203557456    60%    /

하지만 이 출력이 너무 투박해 보입니다. 두 번째 줄의 첫 번째 "단어"를 얻기 위해 구문 분석하는 것보다 더 좋은 방법이 있습니까?

나에게 정말로 필요한 것은 다음 명령으로 파이프할 수 있도록 하는 것과 같은 것입니다.

$ somecommand .
/dev/disk0s2

"df" 출력에서 ​​문자열 해킹을 사용하지 않고 이를 달성하려면 어떻게 해야 합니까?

답변1

셸만 사용하여 이 작업을 수행할 수 있습니다( bash, dash, ksh, 에 적용 zsh).

df . | (read a; read a b; echo "$a")

또는 출력이 필요하지 않고(결과는 $a에 저장됨) 쉘이 프로세스 대체를 지원하는 경우(예: bash, zsh):

{ read; read a b;}< <(df .)

다음은 다른 솔루션의 속도와의 몇 가지 비교입니다.

# pure shell solution 1

bash-4.2$ time for i in $(seq 500); do df . | (read a; read a b; echo "$a"); done > /dev/null
1.899

(dash) $ time -f '%e' dash -c 'for i in $(seq 500); do df . | (read a; read a b; echo "$a"); done > /dev/null'
1.05

(ksh) $ time for i in $(seq 500); do df . | (read a; read a b; echo "$a"); done > /dev/null
    0m1.16s real     0m0.02s user     0m0.12s system

(zsh) manatwork% time (for i in $(seq 500); do df . | (read a; read a b; echo "$a"); done > /dev/null)
1.51s

# pure shell solution 2

bash-4.2$ time for i in $(seq 500); do { read; read a b;}< <(df .); done
1.192

(zsh) manatwork% time (for i in $(seq 500); do { read; read a b;}< <(df .); done)
3.51s

# other solutions

bash-4.2$ time for i in $(seq 500); do df . | tail -1 | cut -f 1 -d " "; done > /dev/null
1.405

bash-4.2$ time for i in $(seq 500); do df . | sed '2!d' | awk '{print $1}'; done > /dev/null
5.407

bash-4.2$ time for i in $(seq 500); do df . | sed -n '2{s/ .*$//;p}'; done > /dev/null
1.767

bash-4.2$ time for i in $(seq 500); do df . | sed '2!d' | awk '{print $1}'; done > /dev/null
3.334

bash-4.2$ time for i in $(seq 500); do df . | gawk 'NR==2{print $1}'; done > /dev/null
3.013

bash-4.2$ time for i in $(seq 500); do df . | mawk 'NR==2{print $1}'; done > /dev/null
1.747

bash-4.2$ time for i in $(seq 500); do df . | perl -nae 'print$F[0]if$.==2'; done > /dev/null
2.752

( stat여기에서는 작동하지 않으므로 솔루션과 비교되지 않습니다.)

답변2

이것은 일반적으로 그렇습니다UNIX에서의 방법간단한 프로그램의 기능을 비트별로 연결합니다. 따라서 df일부 필터를 통해 출력을 전달하는 것에 대해 걱정하지 마십시오 .

df /path/to/file | sed -n '2{s/ .*$//;p}'

-n자동으로 인쇄 줄을 억제하고, 2{}두 번째 줄에 포함된 명령을 실행하고, s/ .*$//첫 번째 공백의 모든 내용을 버리고 p나머지를 인쇄합니다. 더 긴 입력을 구문 분석하고 두 번째(또는 n번째) 줄만 필요한 상황에서 q추가하면 p작업 속도가 빨라질 수도 있습니다 .

답변3

sed다음과 같은 간단한 한 줄을 사용할 awk수 있습니다 .

df . | sed '2!d' | awk '{print $1}'

에서 sed지정하는 것은 2d두 번째 행을 삭제하는 것을 의미합니다 . !다른 모든 줄을 삭제하고 두 번째 줄을 인쇄하도록 부정을 추가합니다 . 그런 다음 명령은 awk값의 첫 번째 열을 표시합니다.

산출:

/dev/disk0s2

답변4

Linux를 사용하는 경우 findmnt( util-linux패키지의 일부)를 사용할 수 있습니다."스트링 해킹에 의지할 필요가 없습니다":

findmnt -no source -T /path/to/file
/dev/sda1

이 옵션을 사용할 때

-T, --대상
경로가 마운트 지점 파일이나 디렉터리가 아닌 경우 findmnt마운트 지점을 얻기 위해 경로 요소를 역순으로 확인합니다. 다른 두 가지 옵션은 헤더 행을 억제 -n, --noheading하고 나열할 열을 선택합니다.-o, --output


dffrom에는 특정 필드만 인쇄하는 coreutils유사한 옵션이 있습니다 . 예를 들면 다음과 같습니다.--output=source

df --output=source /path/to/file
파일 시스템
/dev/sda1

하지만 제목을 삭제할 수 있는 옵션은 없습니다. 이것이 문제라면 최소한의 조치를 취해야 합니다.문자열 해커예를 들어 파이프로sed 1d

관련 정보