我在用参数和R M和寻找为了删除遵循 find 定义的特定模式的文件,如下所示:
touch file
find . -name file | xargs rm
上面的代码一切正常,但如果我输入 rm 的 -i 选项,然后执行:
touch file
find . -name file | xargs rm -i
印刷:
rm:删除常规空文件“./file7”?用户@主机:$
不让我输入 y 或 n。因此该文件不会被删除。
这里有什么问题?
我还知道 xargs -p 参数有效,但它更通用。即提示用户执行特定的命令,不方便用户操作。
编辑:在 shell 脚本中使用它时,我发现它执行了我想要的命令,但它也打印了 find 的结果,这是不可取的。
另外,当我将ls file2
命令传递给 cmd 变量时,它不会专门打印 file2 的规格。当我输入时也会发生同样的事情
rm -i file2
。它提示我删除目录中的每个文件。
这是我的脚本:
#!/bin/bash
touch file{1..9} # Create 9 files named file1,file2...file9
echo -n 'command: ' # Prompt user
read -e cmd # read command
find . -exec ${cmd} '{}' +
我能想到的唯一解决方案是单独提示用户选择他们喜欢的模式。然后将该模式存储到一个变量并将其作为参数传递给寻找命令的-姓名选项。
像这样的东西:
#!/bin/bash
touch file{1..9} # Create 9 files named file1,file2...file9
echo -n 'command: ' # Prompt user for command
read -e cmd # read command
echo -n 'pattern: ' # Prompt user for pattern
read -e pattern
find . -name "$pattern" -exec ${cmd} '{}' +
但即使有了这个解决方案,寻找的输出仍会被打印,并且如果模式字段留空(即,用户只是不想使用模式),那么就会出现问题。
有任何想法吗?
答案1
xargs 从 stdin 读取数据。当您使用rm -i
rm 时,还会尝试从 stdin 读取答案( try touch test && echo y | r -i test ; ls test
),但 stdin 被 xargs 关闭(我假设),因此 rm 的反应就像您在提示符下按了 ctrl-d 一样。
另一个解决方案可能是 find 的 -exec 选项:
touch test
find . -name test -exec rm -i {} \;
答案2
您可以使用POSIX -ok
选项find
让它询问您是否继续执行命令(除了提示之外,它就像-exec
)
touch file
find . -name 'file' -ok rm -f {} \;
输出
< rm ... ./file > ? _
答案3
这里的问题是,从(在本例中)stdin
运行的命令的(标准输入)从重定向,并且是用于获取用户确认的文件描述符。xargs
rm
/dev/null
stdin
rm
您可以使用该-a
选项,以便 rm 从先前由 find 命令生成的中间文件中获取文件列表(该-a
选项使xargs
不受影响stdin
),无论如何,我知道这可能不是您真正想要的,因为它需要中间文件。可以使用以下命令获得与您想要的类似的更直接的方法:
for i in $(find . -name file); do rm -i "$i"; done
答案4
我遇到了类似的问题,当命令出现时我感到很惊讶
find . -type f -name "*.txt" | xargs rm
意外删除了与该模式匹配的只读文件。
后来我才在man page中找到了解释rm
:
如果文件不可写,标准输入是终端,并且未给出 -f 或 --force 选项,或者给出了 -i 或 --interactive=always 选项,则 rm 会提示用户是否删除该文件。
获得提示的条件之一是标准输入是终端,当您将另一个命令的输出通过管道传输到rm
.
重要教训:如果 stdin 不是终端,rm
将删除只读文件,而不会发出任何警告!
就我而言,解决方案是将find
命令修改为仅返回可写文件:
find . -type f -writable -name "*.txt" | xargs rm