我想用这个脚本执行的操作是
- 读取目录中每个文件的名称(不带基数)
- 对于每个文件,询问用户是否要执行操作(例如移动目录中的文件)
执行或不执行该操作。
我的 while 循环和读取输入有问题。我尝试过这个:
#! /bin/csh -f set DIR = 'pwd' find $DIR -name * -exec basename {} \; | while read filename do read -p $filename" (y or n?)" choice if ($choice = "y") then <> endif end
但我收到错误:
find: `basename' terminated by signal 13.
我也在考虑再次使用一段时间来扩展用户的输入,直到给出“是”或“否”,但这是一个二阶问题。
答案1
bash
即使您使用#!
-line 指定,您的 shell 代码的一部分看起来也像代码csh
。csh
没有read
命令,这就是您收到signal 13
错误的原因。
信号 13 是 PIPE 信号,当进程尝试写入死管道(没有人从另一端读取的管道)时,它会被发送到进程。管道已死,因为循环read
中的调用失败while
。它失败了,因为它在csh
.
如果 csh
如果有一个read
命令,你的循环将获取文件名,但你不会有任何方式知道在哪里这些文件名属于(在哪个子目录中),因为您从中删除了目录路径。因此,您将无法对它们做太多事情。
这最简单的这样做的方法是find
向用户询问问题:
find . -type f -ok some-action '{}' ';'
some-action
在使用路径名作为参数执行实用程序之前,这将要求确认每个路径名。它会询问将为给定路径名执行的完整命令行,因此这并不完全是您想要的。
另请注意,指定-type f
将查找所有常规文件,而您的-name '*'
测试将总是适用于所有类型的文件,包括目录。我还使用.
(当前目录)作为 的顶级目录find
,这似乎是您想要对DIR
变量执行的操作。
要手动要求用户输入每个文件,同时正确处理路径名,最简单的方法是执行以下操作
find . -type f -exec sh -c '
for pathname do
printf "process %s (%s)?\n" "${pathname##*/}" "$pathname" >&2
read answer
case $answer in [Nn]*) continue; esac
printf "processing %s...\n" "$pathname" >&2
# process "$pathname" here
done' sh {} +
这假设有一个sh
类似 shell,并将生成sh -c
由 找到的批量路径名find
。内部 shell 脚本会询问用户是否愿意处理每个单独的路径名。如果用户回答以n
(不区分大小写)开头的单词,则将考虑下一个路径名。
"${pathname##*/}"
代码中的位相当于删除"$( basename "$pathname" )"
最后$pathname
一个斜杠之前的所有内容(包括最后一个斜杠)。
该find
命令充当一种路径名生成器对于for
内部脚本中的 -loop,因此while
无需将路径名或文件名通过管道传输到 -loop。
有关的: