我最近开始使用 Linux,所以我的程序仅供学习。话虽如此,这是我的代码:
#include <stdio.h>
#include <stdlib.h>
int main () {
FILE *fin;
char buf[200];
fin = fopen("provaMake.txt", "r");
if (fin==NULL) {
fin = fopen("/home/giorgio/Desktop/provaMake.txt", "r");
if (fin==NULL) {
printf("finError\n");
exit(1);
}
}
while(fgets(buf, 200, fin) != NULL) {
system(buf);
}
fclose(fin);
}
这是provaMake.txt
文件:
cd /home/giorgio/Desktop/a
rm -f pippo.txt
cd /home/giorgio/Desktop
当我使用以下命令运行它时:
$gcc provaMake.c -o provaMake.o
$./provaMake.o
它没有删除 pippo.txt (位于a
目录内部Desktop
)。
我在代码中做错了什么吗?我再说一遍,我正在努力学习,所以请向我解释一下(或者告诉我在哪里可以学习)。
答案1
system()
在 shell 中运行命令。该 shell 是一个新的过程。它是你的 C 程序的一个子进程。该cd
命令更改运行它的 shell 进程的当前目录。该 shell 的子进程将继承该目录。但它不会影响父进程的当前目录。
您调用了system()
三次。每次都会启动一个 shell 进程,运行一个命令,然后结束。cd
一次调用system()
不会影响单独调用的当前目录system()
。
如果你必须使用system()
,那么解决问题的最佳方法可能是避免使用cd
,而只需用一个命令完成所有操作。但这只有在你可以更改 时才有效provaMake.txt
。具体来说,这应该像 的内容一样工作provaMake.txt
:
rm -f /home/giorgio/Desktop/a/pippo.txt
如果你必须使用system()
但不能或不想更改provaMake.txt
,或者你特别感兴趣如何使用system()
运行文件中的所有命令在同一个 shell 进程中,那么您可以传递system()
一个硬编码命令,该命令启动一个新 shell 并在同一 shell 中运行该文件中的所有命令。例如,您的 C 程序可以使用以下代码:
system(". /home/giorgio/Desktop/provaMake.txt");
您可以使用该命令替换整个程序。不需要缓冲区,因为您的 C 程序本身并不从文件中读取。同样,也不fopen()
需要调用。shell 负责打开、读取文件并执行文件中的命令 - 这是其.
内置操作,使用任何 Bourne 风格的 shell 时都会出现。(system()
使用sh
,它是 Bourne 风格的 shell,原样bash
)。
请注意,如果您的 C 程序随后依赖或以其他方式观察其当前工作目录,那么它仍然不会受到cd
运行的命令的影响(就像在您的原始代码中一样),因为它们仅在 shell 中运行。
有时,出于学习目的,以人为的方式做事是合理的,所以我不想告诉你不要编写一个 C 程序来system()
逐个运行文件中所有的 shell 命令。但是,如果你的实际目标只是运行文件中的所有命令,那么你不需要 C 程序。你可以直接使用你的 shell:
如果你想在你的当前的shell 进程,以便它的环境受到影响 - 例如,以便
cd
命令的效果之后仍然存在 - 那么您只需运行:. /home/giorgio/Desktop/provaMake.txt
如果你想在新的shell,这样当前shell的环境就不会受到影响,然后将文件的名称作为命令行传递给shell:
bash /home/giorgio/Desktop/provaMake.txt
如果您正在使用的或想要使用的 shell 不是 bash,则可以调整该命令。例如:
sh /home/giorgio/Desktop/provaMake.txt
您可能希望使命令列表本身可执行。为此,请在开头添加类似以下内容(根据应使用哪个 shell 来解释它进行调整):
#!/bin/bash
并通过运行以下命令更改其权限以使其可执行:
chmod +x filename
代替
filename
替换为实际的文件名,例如/home/giorgio/Desktop/provaMake.txt
。然后您可以像运行任何程序一样运行该文件:
./provaMake.txt # when you're in the directory that contains it
/home/giorgio/Desktop/provaMake.txt # from anywhere
尤其是在最后一种情况下,用后缀命名文件是不常见的.txt
。通常,内容将通过.
内置命令运行的文件通常用后缀命名.sh
,而将被标记为可执行文件并作为脚本运行的文件则不带后缀。(不过,就 shell 和操作系统而言,文件名并不重要。)
答案2
我不知道为什么它对你不起作用,当我尝试类似的东西时它起作用了。
无论如何,添加一些printf
语句对于理解程序正在做什么非常有帮助。例如,尝试在 while 循环中调用之前添加此行system
:
printf("Now calling system() with buf = %s\n", buf);
然后再次编译并运行并查看输出,希望这能帮助您了解发生了什么。