[英]Passing arguments through bash script to C program
我正在尝试编写一个程序,将文件名作为bash脚本中的参数,然后将其传递给用下划线替换空格的C程序,然后bash脚本使用它来重命名文件。
例如,输入为
Bash bash_script "test test test.txt"
并且该文件将重命名为test_test_test.txt
。
我的问题是,当我运行此命令时,它告诉我我使用的mv
错误。 为什么是这样? 我是bash的新手,所以对不正确使用程序/脚本感到抱歉。
我的C程序:
#include <stdio.h>
int main(int argc, char *argv[])
{
int i = 0;
char * file = argv[1];
while(i<=256){ //max file size is 256 characters on mac
if (argc != 2)
printf("Please provide one file name.");
else if(file[i] == ' ')
file[i] = '_';
i++;
}
printf("%s \n", file);
return 0;
}
我的Bash程序:
#! /bin/bash
VAR = "C_program '$@'"
mv $1 $VAR
这行:
VAR = "C_program '$@'"
不会做你想要的。 而且您的mv
线也坏了。
VAR=$(C_program "$@")
mv "$1" "$VAR"
同样,当检测到错误时,您的C程序也不会错误退出。
此外, sed
和tr
是现有程序,可以替代编写C程序以音译( 转换 )字符串中的字符的方式。
另外, rename
/ prename
rename
是现有的(Perl)程序,该程序处理具有正则表达式模式功能的重命名文件来重命名文件,这些文件可能已在您的系统上可用。
在您的特定示例中,我不会使用定制的C程序来执行此操作。
这是等效的shell脚本(不需要tr
, sed
或bash
和mv
之外的任何程序):
mv "$1" "${1// /_}"
在您的特定问题中,您没有正确设置VAR
。 Shell脚本在设置变量时不能接受=
周围的空格,并且您需要使用反引号或$()
来执行外部程序。 所以,写得好,你要
VAR="$(C_program "$@")"
mv $ 1“ C_program'$ @'”的2个问题
但是,这可以更有效地完成
IFS="
"
for x in $@; do
mv "$x" "${x// /_}"
done
如果您只想要结果,则建议只用一个简短的Bourne或POSIX shell脚本替换bash脚本和自定义C程序。
#!/bin/sh
NEW_FILE_NAME= `echo $1 | tr ' ' _ `
mv $1 $NEW_FILE_NAME
除此以外
在设置shell变量VAR
之前,您希望shell脚本运行C程序(为简单起见,我将其称为todash
)。 这可以通过使用反引号 `(位于带代号'〜'的美式键盘的右上角附近)来完成。
#!/bin/sh
VAR= `todash $1`
mv $1 $VAR
对于todash.c,我将提出几个主要的小改进。
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
int main(int argc, char *argv[])
{
char * filename;
/* Program operates on filename, not file or its contents, so use a variable
name that reflect that. Good variable names make debugging easier.
*/
if (argc != 2) {
printf("Please provide one file name.");
return EXIT_FAILURE; /* or exit(EXIT_FAILURE); */
} else {
/* Only set filename, once known that argv[1] is not NULL (empty) */
filename = argv[1];
}
/* Use a simple for loop
* PATH_MAX is a standard system constant included with limits.h
*/
for (i = 0; (i < PATH_MAX) && (filename[i] != '\0'); i++) {
if (filename[i] == ' ') {
filename[i] = '_';
}
}
printf("%s \n", filename);
return EXIT_SUCCESS;
}
添加的长度仅是我的其他内联注释。
最大的变化是解开的argc
if
从比较while
循环,曾经简化,成为这里使用一个典型的例子for
循环。
为使您和周围的人保持理智,请在条件代码块周围使用花括号(花括号)。 仅仅因为允许您不包括它们,并不意味着您应该(不包括它们)。 程序往往超出了最初的意图,并在将来扩展。 现在就将它们包括在内,避免以后再犯错误。
我大部分时间是第二个mctylr,但建议使用更干净的循环版本:
for ( ; *file != '\0'; file++ ) {
if ( *file == ' ' ) *file = '_';
}
这就是数组指针的力量。 现在,您节省了约4个字节,并有一些漂亮的代码可以启动。
但是,这远非仅仅是一次改头换面。 你的代码实际上是非常危险的,因为如果“的argv [1]” 是少于256个字符,你正在阅读的任意内存过去的数组边界和潜在写它 (在一个假设的情景,其中filepath是一个长度为0,下一个255个空格内存中的内容将更改为下划线。)
相反,请检查这是否等于true:
if ( strlen ( argv[1] ) > 256 )
...并退出并返回错误。 然后读取argv [1]。
如果我有任何问题,请纠正我,我绝不是专家。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.