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的工作目录。保持不变

这个答案的其余部分讨论了如何使用GNU
find
解决这个问题

-execdir
解决方案也可以与BSD/OSX
find
一起使用,而且实际上更简单


至于获取
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/OSX
find
并没有表现出这种怪癖:它总是将
{}
扩展到仅仅是文件名,而没有任何路径组件。

虽然这个代码片段可以解决这个问题,但确实有助于提高文章的质量。请记住,您将在将来回答读者的问题,这些人可能不知道您的代码建议的原因。此建议根本解决不了任何问题,因为它完全忽略了MY-exec flag选项。这似乎有一段时间有效,然后“Cannot stat:没有这样的文件或目录”也许xargs不能处理太多的文件?这个答案正确地显示了如何只打印文件名(这是OP要求的事情之一——尽管在解决另一个问题的错误尝试中)。但是,使用GNU
find
(在Linux上可以找到)的一个更简单、更高效的解决方案是
find/path/to/directory/*-maxdepth 0-type d-printf“%f\n”
。使用
-exec
并假设GNU或BSD/OSX
basename
,更有效的解决方案是
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"' - {} \;