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: