我想找到所有的文件,不是硬链接或硬链接目录下。我找到了这个太棒了,但是下面的命令不处理硬链接目录下的情况!
find /1 -type f -links 1 -print例如:
/1/2/3/test.txt
/1/A/3/test.txt2是硬链接到A,那么我们只期望找到一个test.txt文件。
android的另一个例子是:
$ adb shell ls -li /data/data/com.android.nfc |grep files
4243 drwxrwx--x 2 nfc nfc 3488 2022-06-13 11:08 files
$ adb shell ls -li /data/user/0/com.android.nfc |grep files
4243 drwxrwx--x 2 nfc nfc 3488 2022-06-13 11:08 files
$ adb shell ls -li /data/data/com.android.nfc/files/service_state.xml
5877 -rw------- 1 nfc nfc 100 2022-06-13 11:08 /data/data/com.android.nfc/files/service_state.xml
$ adb shell ls -li /data/user/0/com.android.nfc/files/service_state.xml
5877 -rw------- 1 nfc nfc 100 2022-06-13 11:08 /data/user/0/com.android.nfc/files/service_state.xml发布于 2022-06-13 22:19:19
支持指向目录的无限制硬链接的系统很少,但是可以使用绑定挂载创建类似的情况。(见什么是绑定坐骑?.)
尝试使用此谢尔查克-clean代码列出当前目录下没有多个路径的文件(由绑定挂载或指向目录的链接引起):
#! /bin/bash -p
shopt -s lastpipe
declare -A devino_of_file
declare -A count_of_devino
find . -type f -printf '%D.%i-%p\0' \
| while IFS= read -r -d '' devino_path; do
devino=${devino_path%%-*}
path=${devino_path#*-}
devino_of_file[$path]=$devino
count_of_devino[$devino]=$(( ${count_of_devino[$devino]-0}+1 ))
done
for path in "${!devino_of_file[@]}"; do
devino=${devino_of_file[$path]}
(( ${count_of_devino[$devino]} == 1 )) && printf '%s\n' "$path"
doneshopt -s lastpipe确保管道中的while循环中设置的变量在管道完成后保持不变。它需要Bash 4.2 (2011年发布)或更高版本。.字符分隔。devino字符串应该唯一地标识系统上的文件,而不依赖于它的任何路径。devino_of_file关联数组将路径映射到相应的devino值。count_of_devino关联数组将devino字符串映射到它们找到的路径数。while IFS= read -r -d '' ...。'%s\n'格式字符串),输出将是无用的。find不遵循符号链接。但是,如果使用-follow选项到find,代码仍然可以工作。(使用符号链接测试比使用目录硬链接或绑定挂载更容易。)注意,Bash代码运行非常慢。它是以一种非常艰苦的方式解释的。如果正在处理的目录树有大量文件,那么上面的代码可能会太慢。例如,它在我的测试VM上以每秒大约10,000的速度处理文件。
发布于 2022-06-13 18:01:31
请原谅评论中的幽默,但我认为你不明白你的问题。
我的意思是,当您创建一个文件时,它就是一个链接。
$: date > file1
$: ls -l file1 # note the 2nd field - the "number of hard links"
-rw-r--r--. 1 P2759474 518 29 Jun 13 17:34 file1您认为file1是文件,但它是...complicated,lol。
上面的date命令创建输出。重定向告诉“系统”您想要“文件”中的数据,因此它分配磁盘上的空间,将数据写入该空间,并创建定义“文件”的inode。
“硬链接”基本上就是指向该数据的链接。如果您创建了另一个链接,那么它是同一个带有其他名称的“文件”。编辑两者都是(如果你做了几个编辑),因为它们是同一个文件。
$: date >file1
$: ln file1 file2
$: diff file?
$: cat file1
Mon Jun 13 17:30:22 GMT 2022
$: date >file2
$: diff file?
$: cat file1
Mon Jun 13 17:31:06 GMT 2022现在,符号链接是另一种具有不同inode的文件,包含它“链接”到的文件的名称,但是硬链接是文件。实际上,ls -i将向您显示inode索引号。
$: date >file1
$: ln file1 file2
$: diff file?
$: cat file2
Mon Jun 13 17:34:41 GMT 2022
$: ls -li file? # note the 1st and 3rd fields
24415801 -rw-r--r--. 2 paul 518 29 Jun 13 17:34 file1
24415801 -rw-r--r--. 2 paul 518 29 Jun 13 17:34 file2
$: rm file2
$: ls -li file? # note the 1st and 3rd fields
24415801 -rw-r--r--. 1 P2759474 518 29 Jun 13 17:34 file1让我们用这个名称创建一个不同的文件,然后再进行比较。
$: date >file2
$: cat file? # not linked now
Mon Jun 13 17:34:41 GMT 2022
Mon Jun 13 17:41:23 GMT 2022
$: diff file? # now they differ
1c1
< Mon Jun 13 17:34:41 GMT 2022
---
> Mon Jun 13 17:41:23 GMT 2022
$: ls -li file? # and have different inodes, one link each
24415801 -rw-r--r--. 1 P2759474 518 29 Jun 13 17:34 file1
24419687 -rw-r--r--. 1 P2759474 518 29 Jun 13 17:41 file2如果我cad复制了原始数据,diff将是空的,但是它仍然是一个不同的inode,所以有一个不同的文件,并且我可以独立地编辑它们。
还有一个符号连接-
$: ln -s file1 file3
$: diff file1 file3
$: ls -li file?
24415801 -rw-r--r--. 1 P2759474 518 29 Jun 13 17:34 file1
24419687 -rw-r--r--. 1 P2759474 518 29 Jun 13 17:41 file2
24419696 lrwxrwxrwx. 1 P2759474 518 5 Jun 13 17:44 file3 -> file1打开符号链接通常会打开它的目标文件,但它可能取决于您使用的是什么工具.注意不同之处
您不能在单独的文件系统上创建指向文件的硬链接,因为它不是这样工作的。你可以用一个符号链接。
你可能要找的是
for f in *; [[ -f "$f" ]] && echo "$f"; done或者类似的东西。
希望这能有所帮助。
发布于 2022-06-13 20:25:58
从以前对这个答案的编辑的评论来看,复制似乎是因为一些文件由于绑定挂载而出现在文件系统中的两个不同位置。
在这种情况下,您使用的原始代码会产生技术上正确的输出。但是,它不止一次地列出了一些相关文件(因为它们有多个名称):
find /1 -type f -links 1 -print安装的文件系统由其设备编号唯一标识。文件在该文件系统中通过其inode编号进行唯一标识。因此,文件可以由(device#,inode#)元组在特定主机上唯一标识。find可以提供这些元组和文件名,如@pjh的回答所示:
find /1 -type f -links 1 -printf '%D.%i %p\0'一个简单的(GNU) awk脚本可以过滤输出,以便只列出每个唯一的路径(device#,inode#):
find /1 -type f -links 1 -printf '%D.%i %p\0' |
gawk -v RS='\0' '!id[$1]++ && sub(/^[0-9.]+ /,"")'这使用了常见的awk成语!x[y]++,只有当元素y被插入数组x时才会计算为true (它是用值0插入的,第一次看到y,然后值就增加了;!0是真的)。(device#,inode#)前缀被sub()删除。如果“模式”的计算结果为true,awk将隐式打印已处理的记录。即。当第一次看到(device#,inode#)元组并成功地删除前缀时。(GNU) find输出由null而不是换行符分隔,因此(GNU) awk脚本也将输入记录分隔符RS设置为null。
https://stackoverflow.com/questions/72606124
复制相似问题