Unix 为什么我使用read命令没有达到预期的效果?

Unix 为什么我使用read命令没有达到预期的效果?,unix,shell,stdin,Unix,Shell,Stdin,我在我的电脑上做了一些破坏,当我玩维祖尔特建议的命令时,我希望一行程序要求删除文件名。但是,它立即删除了文件夹中的我的文件: > find ./ -type f | while read x; do rm "$x"; done 我希望它能等待我输入stdin:s。我无法理解它的行动。read命令是如何工作的,您在哪里使用它?这里发生的是read从stdin读取。当你把它放在一根管子的末端时,它从管子上读出来 所以你的发现变成了 file1 file2 等等read读取并依次用file1

我在我的电脑上做了一些破坏,当我玩维祖尔特建议的命令时,我希望一行程序要求删除文件名。但是,它立即删除了文件夹中的我的文件:

> find ./ -type f | while read x; do rm "$x"; done

我希望它能等待我输入stdin:s。我无法理解它的行动。read命令是如何工作的,您在哪里使用它?

这里发生的是
read
stdin
读取。当你把它放在一根管子的末端时,它从管子上读出来

所以你的发现变成了

file1
file2
等等
read
读取并依次用
file1
file2
替换
x
,因此循环变为

rm“文件1” rm“文件2”

果然,rm的每个文件都从当前目录“”开始

一些提示

您不需要“/”。 这样说更好更安全

 find . -type f
因为如果您碰巧键入“
/
”(即点空格斜杠),find将从当前目录开始,然后从根目录开始查找。如果获得正确的权限,该技巧将删除计算机中的每个文件。“
”已经是目录名;您不需要添加斜杠

find或rm命令将执行此操作 听起来您想做的是从当前目录“
”开始,检查所有目录中的所有文件,并让它询问您是否要删除它。你可以这样做

 find . -type f -exec rm -i {} \;

而且根本不需要一个循环。你也可以

 rm -r -i *
并且得到几乎相同的效果,只是它也会尝试删除目录。如果目录是空的,这甚至可以工作

另一种想法 想想看,除非你有很多文件,否则你也可以这样做

rm -i `find . -type f`

现在,反引号中的find将成为命令行上的一组文件名,
rm
上的“
-i
”交互标志将询问是或否问题。

Charlie Martin对您的特定示例的错误进行了很好的剖析和解释,但没有解决以下一般问题:

什么时候应该使用read命令? 答案是——当您想从某个文件中读取连续的行(很可能是管道中以前的某个命令序列的标准输出)时,可能会将这些行拆分为几个单独的变量。拆分是使用当前值“
$IFS
”完成的,这通常意味着在空格和制表符上(换行符在此上下文中不计算;它们分隔行)。如果read命令中有多个变量,则第一个字进入第一个变量,第二个字进入第二个变量,…,行的剩余部分进入最后一个变量。如果只有一个变量,则整行都会进入该变量

有很多用途。这是使用拆分选项的较简单脚本之一:

#!/bin/ksh
#
#   @(#)$Id: mkdbs.sh,v 1.4 2008/10/12 02:41:42 jleffler Exp $
#
#   Create basic set of databases

MKDUAL=$HOME/bin/mkdual.sql
ELEMENTS=$HOME/src/sqltools/SQL/elements.sql

cat <<! |
mode_ansi with log mode ansi
logged with buffered log
unlogged
stores with buffered log
!

while read dbs logging
do
    if [ "$dbs" = "unlogged" ]
    then bw=""; cw=""
    else bw="-ebegin"; cw="-ecommit"
    fi
    sqlcmd -xe "create database $dbs $logging" \
            $bw -e "grant resource to public" -f $MKDUAL -f $ELEMENTS $cw
done
'Osiris JL:'是我的命令行提示符;我在我的“bin”目录中运行了这个
wgrep
'是grep的一个变体,它只匹配整个单词(以避免像'ready'这样的单词)。这说明了我是如何使用它的


read x | | exit
”行用于从标准输入读取响应的交互式脚本,但如果命令获得EOF(例如,如果标准输入来自
/dev/null
),则会退出。

当然!他到底为什么不使用:>查找-类型f-exec rm'{}'\;while这个东西让我头疼。我只是一个试图理解UNIX的初学者。手册的第一部分有很多页。
#!/bin/ksh
#
#   @(#)$Id: mkdbs.sh,v 1.4 2008/10/12 02:41:42 jleffler Exp $
#
#   Create basic set of databases

MKDUAL=$HOME/bin/mkdual.sql
ELEMENTS=$HOME/src/sqltools/SQL/elements.sql

cat <<! |
mode_ansi with log mode ansi
logged with buffered log
unlogged
stores with buffered log
!

while read dbs logging
do
    if [ "$dbs" = "unlogged" ]
    then bw=""; cw=""
    else bw="-ebegin"; cw="-ecommit"
    fi
    sqlcmd -xe "create database $dbs $logging" \
            $bw -e "grant resource to public" -f $MKDUAL -f $ELEMENTS $cw
done
Osiris JL: file * | grep 'sh.*script' | sed 's/:.*//' | xargs wgrep read
esqlcver:read version letter
jlss:    while read directory
jlss:                read x || exit
jlss:            read x || exit
jlss:    while read file type link owner group perms
jlss:        read x || exit
jlss:    while read file type link owner group perms
kb: while read size name
mkbod:    while read directory
mkbod:while read dist comp
mkdbs:while read dbs logging
mkmsd:while read msdfile master
mknmd:while read gfile sfile version notes
publictimestamp:while read name type title
publictimestamp:while read name type title
Osiris JL: