我正在尝试编写一个程序,在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
答案 0 :(得分:1)
这一行:
VAR = "C_program '$@'"
没有做你想要的。你的mv
行也被破坏了。
VAR=$(C_program "$@")
mv "$1" "$VAR"
此外,当检测到错误时,您的C程序不会退出并显示错误。
此外,sed
和tr
是现有的程序,它们是编写C程序以在字符串中音译(翻译)字符的合适替代方法。
此外,rename
/ prename
是现有(Perl)程序,它们处理具有正则表达式模式功能的重命名文件,以重命名文件,这些文件可能已在您的系统上可用。
答案 1 :(得分:0)
在您的具体示例中,我不打算使用自定义C程序来执行此操作。
这是一个等效的shell脚本(不需要tr
,sed
或bash
和mv
以外的任何程序):
mv "$1" "${1// /_}"
在您的具体问题中,您没有正确设置VAR
。设置变量时,Shell脚本无法接受=
周围的空格,您需要使用反引号或$()
来执行外部程序。所以,写得好,你想要
VAR="$(C_program "$@")"
答案 2 :(得分:0)
mv $ 1&#34; C_program&#39; $ @&#39;&#34;
的2个问题然而,这可以通过
更有效地完成IFS="
"
for x in $@; do
mv "$x" "${x// /_}"
done
答案 3 :(得分:0)
如果您只想要比我建议的结果,只需用一个简短的Bourne或POSIX shell脚本替换bash脚本和自定义C程序。
#!/bin/sh
NEW_FILE_NAME= `echo $1 | tr ' ' _ `
mv $1 $NEW_FILE_NAME
否则
在设置shell变量todash
之前,您希望shell脚本运行您的C程序(为简单起见,我将其称为VAR
)。这是使用反引号`(位于美国键盘右上角,使用波浪号,'〜')操作完成的。
#!/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
比较,这个简化曾经简化过,成为使用{{1}}循环的典型示例。< / p>
为了您的理智以及周围的人,请在条件代码块周围使用大括号(大括号)。仅仅因为你被允许不包括它们,并不意味着你应该(不包括它们)。计划往往超出其初衷,并在未来扩展。现在可以通过包含它们来避免犯错。
答案 4 :(得分:0)
我大部分是第二个mctylr,但推荐一个更干净的循环版本:
for ( ; *file != '\0'; file++ ) {
if ( *file == ' ' ) *file = '_';
}
这就是数组指针的强大功能。现在你节省了大约4个字节并且有一些漂亮的代码可以启动。
这远非仅仅是改款。您的代码实际上非常危险,因为如果&#39; argv [1]&#39; 小于256个字符,您正在读取超出数组边界的任意内存并可能写入(在假设的情况下,filepath的长度为0,接下来的255个空格在内存中将被改为下划线。)
相反,检查这是否等于true:
if ( strlen ( argv[1] ) > 256 )
...如果有,则退出并出现错误。 然后阅读argv [1]。
如果我有任何不妥,请纠正我,我绝不是专家。