Ubuntu環境下,如何查詢某個檔案,屬於哪個套件

測試環境

以下測試是在「Xubuntu 14.04 64位元」。

前提

以「uname」這個指令為例

uname 用法範例

1
$ uname -a

操作步驟

執行

1
$ dpkg -S uname

會看到(依照系統安裝的套件而定)

1
2
3
4
5
6
7
8
9
10
manpages-posix: /usr/share/man/man1/uname.1posix.gz
coreutils: /usr/share/man/man1/uname.1.gz
manpages-dev: /usr/share/man/man2/oldolduname.2.gz
python3.4-examples: /usr/share/doc/python3.4/examples/scripts/find-uname.py
python2.7-examples: /usr/share/doc/python2.7/examples/Demo/scripts/find-uname.py
coreutils: /bin/uname
klibc-utils: /usr/lib/klibc/bin/uname
manpages-dev: /usr/share/man/man2/olduname.2.gz
manpages-posix-dev: /usr/share/man/man3/uname.3posix.gz
manpages-dev: /usr/share/man/man2/uname.2.gz

然後執行

1
$ whereis uname

會顯示

1
uname: /bin/uname /usr/share/man/man2/uname.2.gz /usr/share/man/man1/uname.1posix.gz /usr/share/man/man1/uname.1.gz /usr/share/man/man3/uname.3posix.gz

可以知道「uname」這個指令,是放在「/bin/uname」這個路徑。

執行

1
$ dpkg -S /bin/uname

會看到

1
coreutils: /bin/uname

最後就可以知道,「uanme」這個指令是屬於「coreutils」這個套件。

注意要有安裝該套件,才有辦法使用「dpkg -S」查到。

1
$ cat /var/lib/dpkg/info/coreutils.list | grep uname

例外狀況

另外有種狀況,即使你安裝了該套件,但有些檔案,你也查不到是屬於哪個套件了。
因為該檔案是透過「dpkg trigger」的機制安裝的。

例如:你查不到「/etc/networks」。

1
$ dpkg -S /etc/networks

會顯示

1
dpkg-query: no path found matching pattern /etc/networks

你可以觀看「/var/lib/dpkg/info/base-files.postinst」。

1
$ cat /var/lib/dpkg/info/base-files.postinst | grep networks

可以看到一行

1
install_from_default /usr/share/base-files/networks      /etc/networks

查看一下「/usr/share/base-files/networks」和「/etc/networks」

1
2
cat /usr/share/base-files/networks
cat /etc/networks

所以用「dpkg -S」找不到檔案屬於哪個套件,可以嘗試到「/var/lib/dpkg/info/」去找。

1
$ grep '/etc/networks' /var/lib/dpkg/info/ -R

附帶一提

另外在「/var/lib/dpkg/info/」可以看到一些跟「base-files」有關的檔案

1
$ ls /var/lib/dpkg/info/base-files* -1

會顯示

1
2
3
4
5
6
/var/lib/dpkg/info/base-files.conffiles
/var/lib/dpkg/info/base-files.list
/var/lib/dpkg/info/base-files.md5sums
/var/lib/dpkg/info/base-files.postinst
/var/lib/dpkg/info/base-files.postrm
/var/lib/dpkg/info/base-files.preinst

你可以下載「base-files」,「解開來看」。

1
2
3
apt-get download base-files
dpkg -e base-files_7.2ubuntu5.2_amd64.deb
tree DEBIAN

就會看到

1
2
3
4
5
6
7
8
9
DEBIAN
├── conffiles
├── control
├── md5sums
├── postinst
├── postrm
└── preinst

0 directories, 6 files

確認一下「DEBIAN/postinst」是不是和「/var/lib/dpkg/info/base-files.postinst」一樣。

執行

1
$ md5sum DEBIAN/postinst

顯示

1
29eac8bafe921c9e7a537cd58e272fae  DEBIAN/postinst

執行

1
$ md5sum /var/lib/dpkg/info/base-files.postinst

顯示

1
29eac8bafe921c9e7a537cd58e272fae  /var/lib/dpkg/info/base-files.postinst

另一個檔「/etc/default/locale」也是蠻特殊的,「dpkg -S」找不到。

執行

1
$ dpkg -S /etc/default/locale

顯示

1
$ dpkg-query: no path found matching pattern /etc/default/locale

所以

1
$ grep '/etc/default/locale' /var/lib/dpkg/info/ -R

會顯示

1
2
3
4
/var/lib/dpkg/info/dictionaries-common.config:    # If system is already installed use /etc/default/locale contents.
/var/lib/dpkg/info/dictionaries-common.config: if ( -e "/etc/default/locale" ){
/var/lib/dpkg/info/language-selector-common.postinst:if dpkg --compare-versions "$2" lt-nl 0.85 && [ -e /etc/default/locale ] \
/var/lib/dpkg/info/language-selector-common.postinst: . /etc/default/locale

待研究…

例外狀況 - alternatives

另外有一種情況,是透過「update-alternatives」的方式。

例如「/usr/bin/write」。

執行

1
$ type write

顯示

1
write is /usr/bin/write

執行

1
$ whereis write

顯示

1
write: /usr/bin/write /usr/bin/X11/write /usr/share/man/man2/write.2.gz /usr/share/man/man1/write.1posix.gz /usr/share/man/man1/write.1.gz /usr/share/man/man3/write.3posix.gz

執行

1
$ dpkg -S /usr/bin/write

顯示

1
dpkg-query: no path found matching pattern /usr/bin/write

執行

1
$ ls /usr/bin/write -l

顯示

1
lrwxrwxrwx 1 root root 23 Apr 21  2014 /usr/bin/write -> /etc/alternatives/write

執行

1
$ ls /etc/alternatives/write -l

顯示

1
lrwxrwxrwx 1 root root 18 Apr 21  2014 /etc/alternatives/write -> /usr/bin/bsd-write

執行

1
$ dpkg -S /usr/bin/bsd-write

顯示

1
bsdmainutils: /usr/bin/bsd-write

最後就找到「bsdmainutils」這個套件。

參考