shell cd命令在while中不能作用于while外面,cd在for if case中会作用于for和if和case外面

14 篇文章 1 订阅
博客探讨了在Bash shell中,while、for、if、case命令中使用cd改变目录的效果。在while循环中,cd仅在循环内部生效,因为会启动一个新的子进程;而在for、if、case中,cd的影响会延续到块之外,因为它们不创建新的子进程。通过检查进程ID和使用ps命令验证了这一现象。
摘要由CSDN通过智能技术生成

一. 现象

while中cd在退出while后失效,for & if & case中cd在退出块后生效。

1. while中cd在退出while后失效
$ echo line_1 > ~/1
$ echo line_2 >> ~/1
$ pwd;cat ~/1 | while read l;do echo $l;cd /folder2;pwd;done;pwd
/folder1
line_1
/folder2
line_2
/folder2
/folder1
2. for中cd在退出for后仍有效
$ pwd;for l in `cat ~/1`;do echo $l;cd /folder2;pwd;done;pwd
/folder1
line_1
/folder2
line_2
/folder2
/folder2
3. if中cd在退出if后仍有效
$ pwd;if [ "1" == "1" ] ; then cd /folder2;pwd;fi;pwd
/folder1
/folder2
/folder2
4. case中cd在退出case后仍有效
$ pwd;i="1";case $i in 1)cd /folder2;pwd; ;; esac;pwd
/folder1
/folder2
/folder2

二. while & for & if & case块内并没有开新进程

猜测原因,难道while中开了子进程, 而for & if & case 中没有开子进程,所以while中cd无效、for & if & case中cd有效?
来测试一下。
变量"$$"就是当前进程号。

1. while里进程号不变
$ pwd;echo "current pid : $$";cat ~/1 | while read l;do echo $l;cd /folder2;pwd;echo "current pid : $$";done;pwd;echo "current pid : $$";
/folder1
current pid : 20007
line_1
/folder2
current pid : 20007
line_2
/folder2
current pid : 20007
/folder1
current pid : 20007
2. for里进程号不变
$ pwd;echo "current pid : $$";for l in `cat ~/1`;do echo $l;cd /folder2;pwd;echo "current pid : $$";done;pwd;echo "current pid : $$";
/folder1
current pid : 20007
line_1
/folder2
current pid : 20007
line_2
/folder2
current pid : 20007
/folder2
current pid : 20007

3. if里进程号不变
$ pwd;echo "current pid : $$";if [ "1" == "1" ] ; then cd /folder2;pwd;echo "current pid : $$";fi;pwd;echo "current pid : $$";
/folder1
current pid : 20007
/folder2
current pid : 20007
/folder2
current pid : 20007
4. case里进程号不变
$ pwd;echo "current pid : $$";i="1";case $i in 1)cd /folder2;pwd;echo "current pid : $$"; ;; esac;pwd;echo "current pid : $$";
/folder1
current pid : 20007
/folder2
current pid : 20007
/folder2
current pid : 20007

进程号没有变。那有没有开线程?
(虽然linux中线程和进程没有区别。。。)

ps -ef|grep -e PID -e $$
可以查看父子进程情况。
这个命令可以过滤查看当前进程(进程号$$)的关联父子进程.PID一列是子进程号,PPID是父进程号。

三. while内开了bash子线程,for & if & case内不会开bash子线程。

1. whlie里多了个bash的子线程
$ pwd;echo "current pid : $$";ps -ef|grep -e PID -e $$;cat ~/1 | while read l;do echo $l;cd /folder2;pwd;echo "current pid : $$";ps -ef|grep -e PID -e $$;done;pwd;echo "current pid : $$";ps -ef|grep -e PID -e $$;
/folder1
current pid : 20007
UID        PID  PPID  C STIME TTY          TIME CMD
peggy    19230 20007  0 11:27 pts/20   00:00:00 ps -ef
peggy    20007 20006  0 9月08 pts/20  00:00:00 -bash
line_1
/folder2
current pid : 20007
UID        PID  PPID  C STIME TTY          TIME CMD
peggy    19233 20007  0 11:27 pts/20   00:00:00 -bash
peggy    20007 20006  0 9月08 pts/20  00:00:00 -bash
line_2
/folder2
current pid : 20007
UID        PID  PPID  C STIME TTY          TIME CMD
peggy    19233 20007  0 11:27 pts/20   00:00:00 -bash
peggy    20007 20006  0 9月08 pts/20  00:00:00 -bash
/folder1
current pid : 20007
UID        PID  PPID  C STIME TTY          TIME CMD
peggy    19238 20007  0 11:27 pts/20   00:00:00 ps -ef
peggy    20007 20006  0 9月08 pts/20  00:00:00 -bash

其中

peggy    19233 20007  0 11:27 pts/20   00:00:00 -bash

表明
while里多个bash子线程。
ps -ef 子线程可以忽略。

2. wilie里没有新开bash子线程
$ pwd;echo "current pid : $$";ps -ef|grep -e PID -e $$;for l in `cat ~/1`;do echo $l;cd /folder2;pwd;echo "current pid : $$";ps -ef|grep -e PID -e $$;done;pwd;echo "current pid : $$";ps -ef|grep -e PID -e $$;
/folder1
current pid : 20007
UID        PID  PPID  C STIME TTY          TIME CMD
peggy    19314 20007  0 11:28 pts/20   00:00:00 ps -ef
peggy    20007 20006  0 9月08 pts/20  00:00:00 -bash
line_1
/folder2
current pid : 20007
UID        PID  PPID  C STIME TTY          TIME CMD
peggy    19317 20007  0 11:28 pts/20   00:00:00 ps -ef
peggy    20007 20006  0 9月08 pts/20  00:00:00 -bash
line_2
/folder2
current pid : 20007
UID        PID  PPID  C STIME TTY          TIME CMD
peggy    19319 20007  0 11:28 pts/20   00:00:00 ps -ef
peggy    20007 20006  0 9月08 pts/20  00:00:00 -bash
/folder2
current pid : 20007
UID        PID  PPID  C STIME TTY          TIME CMD
peggy    19321 20007  0 11:28 pts/20   00:00:00 ps -ef
peggy    20007 20006  0 9月08 pts/20  00:00:00 -bash
3. wilie里没有新开bash子线程
$ pwd;echo "current pid : $$";ps -ef|grep -e PID -e $$;if [ "1" == "1" ] ; then cd /folder2;pwd;echo "current pid : $$";fi;pwd;ps -ef|grep -e PID -e $$;echo "current pid : $$";ps -ef|grep -e PID -e $$;
/folder2
current pid : 20007
UID        PID  PPID  C STIME TTY          TIME CMD
peggy    19774 20007  0 11:35 pts/20   00:00:00 ps -ef
peggy    20007 20006  0 9月08 pts/20  00:00:00 -bash
/folder2
current pid : 20007
/folder2
UID        PID  PPID  C STIME TTY          TIME CMD
peggy    19776 20007  0 11:35 pts/20   00:00:00 ps -ef
peggy    20007 20006  0 9月08 pts/20  00:00:00 -bash
current pid : 20007
UID        PID  PPID  C STIME TTY          TIME CMD
peggy    19778 20007  0 11:35 pts/20   00:00:00 ps -ef
peggy    20007 20006  0 9月08 pts/20  00:00:00 -bash
4. wilie里没有新开bash子线程
$ pwd;echo "current pid : $$";ps -ef|grep -e PID -e $$;i="1";case $i in 1)cd /folder2;pwd;echo "current pid : $$";ps -ef|grep -e PID -e $$; ;; esac;pwd;echo "current pid : $$";ps -ef|grep -e PID -e $$;
/folder2
current pid : 20007
UID        PID  PPID  C STIME TTY          TIME CMD
peggy    19857 20007  0 11:36 pts/20   00:00:00 ps -ef
peggy    20007 20006  0 9月08 pts/20  00:00:00 -bash
/folder2
current pid : 20007
UID        PID  PPID  C STIME TTY          TIME CMD
peggy    19859 20007  0 11:36 pts/20   00:00:00 ps -ef
peggy    20007 20006  0 9月08 pts/20  00:00:00 -bash
/folder2
current pid : 20007
UID        PID  PPID  C STIME TTY          TIME CMD
peggy    19861 20007  0 11:36 pts/20   00:00:00 ps -ef
peggy    20007 20006  0 9月08 pts/20  00:00:00 -bash

四. 结论

  1. while中执行cd命令,在退出while后失效,因为会开一个bash子线程来执行while,子线程内(或者子进程内)的cd不会影响到当前进程。
  2. for & if & case中执行cd命令,在退出while后仍生效,因为不会开一个bash子线程来执行for & if & cae,所以while & if & case块内cd命令会影响到你进程。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值