如何查找文件所在的设备(并在脚本中使用它)?

如何查找文件所在的设备(并在脚本中使用它)?

我想找出我的文件所在的设备,以便我可以在脚本中使用它。我能做到这一点:

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

但这个输出感觉太笨拙了;有没有比解析它来获取第二行的第一个“单词”更好的方法?

我真正需要的是这样的东西,这样我就可以将它传送到下一个命令:

$ somecommand .
/dev/disk0s2

我怎样才能实现这一点,最好不诉诸字符串破解“df”输出?

答案1

您可以单独使用 shell 来完成此操作(适用于bashdashkshzsh):

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

或者,如果不需要输出(结果将保存在 $a 中)并且您的 shell 支持进程替换(如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

您可以使用简单的一行sedawk

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

在 中sed,指定2d意味着删除第二。添加一个!否定,所以它只是删除所有其他行,并打印第二行。然后该awk命令显示第一列值。

输出:

/dev/disk0s2

答案4

如果你使用的是linux,你可以使用findmntutil-linux包的一部分)“无需诉诸字符串黑客”:

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

使用该选项时

-T,--目标小路
如果路径不是挂载点文件或目录,findmnt则按相反顺序检查路径元素以获取挂载点。其他两个选项抑制标题行:-n, --noheading并选择要列出的列:-o, --output


dffromcoreutils有一个类似的选项,--output=可以仅打印某些字段,例如source

df --output=source /path/to/file
文件系统
/dev/sda1

但没有删除标题的选项。如果这是一个问题,你必须做一些最小的事情字符串黑客例如通过管道将其传输到sed 1d

相关内容