编辑注释:这个问题含糊不清,因为它混淆了两个无关的任务:
(a)使用-printf
操作打印仅仅是文件名(没有路径组件),以及
(b)通过-exec
在{}
操作的上下文中传递纯粹的文件名作为参数
(a)被误认为是实施(b)的一种方式
这种混乱导致至少一个回答集中于(a)。
功能
我尝试使用find命令列出某个路径中的所有目录,但在输出中隐藏该路径。 -printf"%P \ n" flag应该隐藏/ 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命令完成所有操作。
答案 0 :(得分:1)
find /path/to/directory/* -maxdepth 0 -type d -exec basename {} \;
找到所有目录find /path/to/directory/* -maxdepth 0 -type d
-exec basename {} \;
- 使用find
答案 1 :(得分:0)
由于您只处理子目录(直接子目录), shell循环可能是更简单的解决方案:
(cd "/path/to/dir" && for d in */; do sudo tar -zcpvf "${d%/}".tar.gz "$d"; done)
我知道您要避免使用cd
,但是将整个命令括在(…)
中,它会在子shell 中运行,因此当前的shell' s工作目录。保持不变。
本答案的其余部分讨论了如何使用GNU find
解决问题。
-execdir
解决方案也适用于BSD / OSX find
,实际上更简单。
至于将find
' -printf
仅打印 文件名,而不使用任何目录组件:使用%f
格式说明符:
find /path/to/dir/* -maxdepth 0 -type d -printf "%f\n"
这将打印指定目录中所有立即子目录的名称。
但是, 打印的内容对使用{}
操作时-exec
展开的内容无效:{}
扩展到路径匹配,它总是包含指定为输入的路径组件。
但是, -execdir
操作可能会为您提供所需内容:
在执行指定的命令
它将{}
扩展为./<filename>
- 即仅仅是文件名(在本例中为目录名),前缀为./
- 并将其传递给指定的命令。
因此:
find /path/to/dir -mindepth 1 -maxdepth 1 -type d -execdir sudo tar -zcpvf {}.tar.gz {} \;
警告:-execdir
的行为与输入路径的后代文件的描述相同;对于输入路径本身,奇怪的是,{}
仍然扩展到输入路径 as
因此,上面的命令不对/path/to/dir/*
使用全局(-maxdepth 0
),而是使用/path/to/dir
并让find
执行包含项目的枚举,其级别为 1 - 因此-maxdepth 1
;由于不应包含输入路径本身,因此必须添加-mindepth 1
。
请注意,行为略有不同:find
始终在枚举中包含隐藏的项,而shell包含了globbing({{ 1}})默认情况下不。
如果*
扩展中的./
前缀应该被删除,则需要做更多工作:
{}
使用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
前缀(./
实际上会剥离任何路径组件) 。
注意伪参数${1##*/}
,shell分配给-
,我们对此不感兴趣; $0
然后变为shell参数{}
。
[1]如果输入路径本身是相对的,则前置$1
;请注意,BSD / OSX ./
没有表现出这种怪癖:它总是将find
扩展为纯文件名,而不包含任何路径组件。