在 find 命令的基本名称上执行

在 find 命令的基本名称上执行

假设我有一个目录结构如下

test
test/a
test/b

现在我想执行一个命令,以便在.文件夹中我可以对文件ab.

所以基本上,我想要这样的东西,我天真地尝试过

find test -type f -exec touch `basename {}` \;

只是,这不会导致空文件ab父目录。假设我的 touch 命令只能采用一个参数。

这将导致像这样的目录结构

a
b
test
test/a
test/b

我知道如何在 bash 脚本中执行此操作,但我对单命令解决方案感兴趣。

答案1

执行bash。

find ... -exec bash -c 'touch "${1##*/}"' btouch {} \;

这里的${1##*/}意思是:从第二个以 a 结尾的参数中删除最长的匹配/,从而保留最后一个之后的所有内容/

btouch可以是任何虚拟名称,以使其正确显示在活动进程列表中 ( ps)

答案2

尝试此操作需要您自担风险:

find test -type f -exec echo touch \"\$\(basename "'{}'"\)\" \; | bash

使用带空格的文件名进行测试。

答案3

尝试execdir使用以下选项find:它执行您在文件目录中指定的命令,仅使用其基本名称作为参数

据我所知,您想在“main”目录中创建“a”和“b”。我们可以通过组合$PWD-execdir选项来做到这一点。看看下面的解决方案。 (这些&& find … ls部分仅用于输出,因此您可以看到效果。您需要在 之前使用该命令&&。)

首先我搭建测试环境:

-----[ 15:40:17 ] (!6293) [ :-) ] janmoesen@mail ~/stack 
$ mkdir test && touch test/{a,b} && find . -exec ls -dalF {} +
drwxr-xr-x 3 janmoesen janmoesen 4096 2012-05-31 15:40 ./
drwxr-xr-x 2 janmoesen janmoesen 4096 2012-05-31 15:40 ./test/
-rw-r--r-- 1 janmoesen janmoesen    0 2012-05-31 15:40 ./test/a
-rw-r--r-- 1 janmoesen janmoesen    0 2012-05-31 15:40 ./test/b

这就是当您使用简单的方法时会发生的情况-exec- 原始文件被触及:

-----[ 15:40:30 ] (!6294) [ :-) ] janmoesen@mail ~/stack 
$ find test -type f -exec touch {} \; && find . -exec ls -dalF {} +
drwxr-xr-x 3 janmoesen janmoesen 4096 2012-05-31 15:40 ./
drwxr-xr-x 2 janmoesen janmoesen 4096 2012-05-31 15:40 ./test/
-rw-r--r-- 1 janmoesen janmoesen    0 2012-05-31 15:40 ./test/a
-rw-r--r-- 1 janmoesen janmoesen    0 2012-05-31 15:40 ./test/b

但是,如果我们$PWD与参数占位符结合{}使用-execdir,我们就可以实现(我认为)您想要的:

-----[ 15:40:57 ] (!6295) [ :-) ] janmoesen@mail ~/stack 
$ find test -type f -execdir touch "$PWD/{}" \; && find . -exec ls -dalF {} +
drwxr-xr-x 3 janmoesen janmoesen 4096 2012-05-31 15:41 ./
-rw-r--r-- 1 janmoesen janmoesen    0 2012-05-31 15:41 ./a
-rw-r--r-- 1 janmoesen janmoesen    0 2012-05-31 15:41 ./b
drwxr-xr-x 2 janmoesen janmoesen 4096 2012-05-31 15:40 ./test/
-rw-r--r-- 1 janmoesen janmoesen    0 2012-05-31 15:40 ./test/a
-rw-r--r-- 1 janmoesen janmoesen    0 2012-05-31 15:40 ./test/b

答案4

调用 shell 对路径进行一些字符串处理。您可以使用${VARIABLE##PATTERN}字符串操作构造来剥离前缀匹配PATTERNVARIABLE模式*/会剥离前导目录名称。

find test -type f -exec sh -c 'for x; do touch "${x##*/}"; done' _ {} +

GNU find 的另一种方法是将其更改为子目录。调用 shell 以更改回原始目录。

find test -type f -execdir sh -c 'cd "$0" && touch -- "$@"' "$PWD" {} +

或者放弃find并使用 zsh。具体来说,添加t 历史修改器作为一个全局限定符

touch test/**/*(:t)

相关内容