[英]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.