簡體   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