繁体   English   中英

通过bash脚本将参数传递给C程序

[英]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程序也不会错误退出。

此外, sedtr是现有程序,可以替代编写C程序以音译( 转换 )字符串中的字符的方式。

另外, rename / prename rename是现有的(Perl)程序,该程序处理具有正则表达式模式功能的重命名文件来重命名文件,这些文件可能已在您的系统上可用。

在您的特定示例中,我不会使用定制的C程序来执行此操作。

这是等效的shell脚本(不需要trsedbashmv之外的任何程序):

mv "$1" "${1// /_}"

在您的特定问题中,您没有正确设置VAR Shell脚本在设置变量时不能接受=周围的空格,并且您需要使用反引号或$()来执行外部程序。 所以,写得好,你要

VAR="$(C_program "$@")"

mv $ 1“ C_program'$ @'”的2个问题

  • $ 1需要双引号->“ $ 1”
  • “ C_program'$ @'”应为`C_program'$ 1'`或$(C_program'$ @')

但是,这可以更有效地完成

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM