Linux查找命令隐藏基本目录
编者按:这个问题模棱两可,因为它将两个不相关的任务混为一谈:Linux查找命令隐藏基本目录,linux,shell,find,Linux,Shell,Find,编者按:这个问题模棱两可,因为它将两个不相关的任务混为一谈: (a) 使用-printf操作仅打印文件名(不带路径组件),以及 (b) 通过{} (a) 被误认为是实现(b)的一种方式。 这种混乱导致至少有一个答案集中在(a)。 我试图使用find命令列出某个路径中的所有目录,但在输出中隐藏该路径。-printf“%P\n”标志应该隐藏/path/to/directory/,但它不起作用: find /path/to/directory/* -maxdepth 0 -type d -print
(a) 使用
-printf
操作仅打印文件名(不带路径组件),以及(b) 通过
{}
(a) 被误认为是实现(b)的一种方式。
这种混乱导致至少有一个答案集中在(a)。 我试图使用find命令列出某个路径中的所有目录,但在输出中隐藏该路径。-printf“%P\n”标志应该隐藏/path/to/directory/,但它不起作用:
find /path/to/directory/* -maxdepth 0 -type d -printf "%P\n" -exec sudo tar -zcpvf {}.tar.gz {} \;
例如,上述命令将使用以下命令创建存档:
/path/to/directory/dir1
/path/to/directory/dir2
/path/to/directory/dir3
如何修改命令以输出以下内容:
dir1
dir2
dir3
请注意:我知道我可以通过cd/path/to/directory/然后使用find命令来完成上述操作,但重要的是我避免使用cd,而是使用单个find命令来完成所有操作
find /path/to/directory/* -maxdepth 0 -type d -exec basename {} \;
查找所有目录find/path/to/directory/*-maxdepth 0-类型d
-exec basename{}代码>-使用find中的结果参数执行命令,因为您只处理子目录(直接子目录),shell循环可能是更简单的解决方案:
(cd "/path/to/dir" && for d in */; do sudo tar -zcpvf "${d%/}".tar.gz "$d"; done)
我知道您希望避免使用cd
,但是通过将整个命令封装在(…)
中,它是在子shell中运行的,因此当前shell的工作目录。保持不变
这个答案的其余部分讨论了如何使用GNUfind
解决这个问题
-execdir
解决方案也可以与BSD/OSXfind
一起使用,而且实际上更简单
至于获取find
-printf
仅打印文件名,而不打印任何目录组件:使用%f
格式说明符:
find /path/to/dir/* -maxdepth 0 -type d -printf "%f\n"
这将只打印指定目录中所有直接子目录的名称
但是,当使用-exec
操作时,打印的内容对{}
扩展到的内容没有影响:{}
始终扩展到匹配的路径,该路径始终包括指定为输入的路径组件
但是,执行-execdir
操作可能会满足您的需求:
- 在执行指定的命令之前,它将更改为当前目录
- 它将
扩展为{}
,即仅为文件名(本例中为目录名),前缀为/
,并将其传递给指定的命令/
-execdir
仅对作为输入路径后代的文件执行所述操作;奇怪的是,对于输入路径本身,{}
仍按原样扩展到输入路径[1]
.
因此,上面的命令不使用globbing(/path/to/dir/*
)和-maxdepth 0
,而是使用/path/to/dir
,让find
对所包含的项进行枚举,而不是在级别1,因此-maxdepth 1
;由于不应包括输入路径本身,因此必须添加-mindepth 1
请注意,随后的行为会有细微的不同:find
始终在枚举中包含隐藏项,而shell的全局搜索(*
)在默认情况下不包含隐藏项
如果应剥离
{}
扩展中的/
前缀,则需要进行更多工作:
find /path/to/dir -mindepth 1 -maxdepth 1 -type d \
-execdir sh -c 'd=${1##*/}; sudo tar -zcpvf "$d".tar.gz "$d"' - {} \;
涉及shell(sh
)允许使用shell参数扩展来剥离/
前缀(${1##*/}
实际上会剥离任何路径组件)。
注意伪参数-
,shell将其分配给$0
,我们对此不感兴趣<代码>{}然后成为shell参数$1
[1] 如果输入路径本身是相对的,则在前面加上
/
;请注意,BSD/OSXfind
并没有表现出这种怪癖:它总是将{}
扩展到仅仅是文件名,而没有任何路径组件。虽然这个代码片段可以解决这个问题,但确实有助于提高文章的质量。请记住,您将在将来回答读者的问题,这些人可能不知道您的代码建议的原因。此建议根本解决不了任何问题,因为它完全忽略了MY-exec flag选项。这似乎有一段时间有效,然后“Cannot stat:没有这样的文件或目录”也许xargs不能处理太多的文件?这个答案正确地显示了如何只打印文件名(这是OP要求的事情之一——尽管在解决另一个问题的错误尝试中)。但是,使用GNUfind
(在Linux上可以找到)的一个更简单、更高效的解决方案是find/path/to/directory/*-maxdepth 0-type d-printf“%f\n”
。使用-exec
并假设GNU或BSD/OSXbasename
,更有效的解决方案是find/path/to/directory/*-maxdepth 0-type d-exec basename-a{}+
。从好的方面来说,这个答案中的命令是POSIX兼容的。这几乎可以工作!除非它在前面放了一个难看的空白目录,例如:./dir/filename.txt。是否有任何方法可以删除./so输出只是dir/filename.txt?是的,tar工作正常,但我得到的不是我的存档中的dir1 dir2。/dir1./dir2.find:path必须在expression之前:-execdir用法:find[-H][L][P][Olevel D][D help | tree | search | stat rates | opt exec][path…][expression]@GTSJoe:听起来像是个打字错误;在-exec
之后的某个地方,您有一个未加引号的/
-也许您忘记了shell命令周围的单引号?如果答案解决了您的问题,请单击大复选标记接受它(✓) 在它旁边。如果你找到其他答案
find /path/to/dir -mindepth 1 -maxdepth 1 -type d \
-execdir sh -c 'd=${1##*/}; sudo tar -zcpvf "$d".tar.gz "$d"' - {} \;