2009-05-07 36 views
7

Tôi có một file có tên cmd có chứa một danh sách các lệnh unix như sau:lệnh Thi chứa không gian trong bash

hostname 
pwd 
ls /tmp 
cat /etc/hostname 
ls -la 
ps -ef | grep java 
cat cmd 

Tôi có một kịch bản mà thực hiện các lệnh trong cmd như:

IFS=$'\n' 
clear 
for cmds in `cat cmd` 
do 
     if [ $cmds ] ; then 
     $cmds; 
     echo "****************************"; 
     fi 
done 

Vấn đề là các lệnh trong cmd không có dấu cách chạy tốt, nhưng các lệnh có dấu cách không được diễn giải đúng bởi tập lệnh. Sau đây là đầu ra:

patrick-laptop 
**************************** 
/home/patrick/bashFiles 
**************************** 
./prog.sh: line 6: ls /tmp: No such file or directory 
**************************** 
./prog.sh: line 6: cat /etc/hostname: No such file or directory 
**************************** 
./prog.sh: line 6: ls -la: command not found 
**************************** 
./prog.sh: line 6: ps -ef | grep java: command not found 
**************************** 
./prog.sh: line 6: cat cmd: command not found 
**************************** 

Tôi thiếu gì ở đây?

Trả lời

13

Hãy thử thay đổi một dòng vào eval $cmds thay vì chỉ $cmds

0

EDIT: Nhận xét của Ben Blank đã chỉ ra rằng câu trả lời cũ của tôi là sai, cảm ơn.

Có vẻ như bạn đang thực hiện các lệnh dưới dạng một chuỗi, vì vậy bash coi chúng là tên tập lệnh/thực thi.

Một cách để tránh điều đó là gọi lệnh bash trên lệnh. Thay đổi:

if [ $cmds ] ; then 
    $cmds; 
    echo "****************************"; 
    fi 

để

if [ $cmds ] ; then 
    bash -c $cmds 
    echo "****************************"; 
    fi 
+1

Thực ra, anh ấy đang gặp vấn đề ngược lại.Đặt $ IFS khi anh ta thực hiện ở đây khiến 'for' phá vỡ trên các dòng mới, chính xác như anh ta muốn. Tuy nhiên, nó sau đó cố gắng để giải thích toàn bộ chuỗi như là một tên lệnh chứ không phải là một lệnh với các đối số. –

+0

+1 để bù đắp downvote. :-) –

+0

bằng cách gọi bash -c bạn đang bắt đầu một quy trình mới cho mỗi lệnh. Điều đó có vẻ quá mức và có thể có kết quả đáng ngạc nhiên. Ví dụ, nếu một trong các lệnh là lệnh cd, các lệnh tiếp theo sẽ không được chạy trong thư mục kia. –

1

Edit: Hóa ra đây không thành công trên đường ống và chuyển hướng. Cảm ơn, Andomar.

Bạn cần thay đổi IFS trở lại bên trong vòng lặp để bash mà biết nơi để phân chia các đối số:

IFS=$'\n' 
clear 
for cmds in `cat cmd` 
do 
    if [ $cmds ] ; then 
     IFS=$' \t\n' # the default 
     $cmds; 
     echo "****************************"; 
     IFS=$'\n' 
    fi 
done 
+0

-1, đã thử điều này, nó không thành công trên lệnh "ps -ef | grep java". – Andomar

3

Bạn có thể thay kịch bản của bạn với lệnh

sh cmd 

Công việc của trình bao là đọc lệnh và chạy chúng! Nếu bạn muốn chỉ báo đầu ra/tiến trình, hãy chạy trình bao trong chế độ tiết chi tiết

sh -v cmd 
2

Cá nhân tôi thích phương pháp này tốt hơn - Tôi không muốn làm mất IFS nếu tôi không phải làm như vậy. Bạn cần phải sử dụng một eval nếu bạn đang sử dụng đường ống trong các lệnh của bạn. Đường ống cần được xử lý bởi trình bao không phải lệnh. Tôi tin rằng vỏ phân tích các đường ống trước các chuỗi mở rộng.

Lưu ý rằng nếu tệp cmd của bạn chứa các lệnh nhập vào sẽ có vấn đề. (Tuy nhiên, bạn luôn có thể tạo ra một fd mới cho lệnh đọc để đọc từ.)

clear 
while read cmds 
do 
     if [ -n "$cmds" ] ; then 
     eval $cmds 
     echo "****************************"; 
     fi 
done < cmd 
+0

proDir = $ {PROJECT_DIR}, trong đó PROJECT_DIR chứa khoảng trống trong thư mục. Đã thử với eval $ {PROJECT_DIR} không hoạt động, Mọi người có đưa ra đề xuất không? – arunit21

0
sed 'aecho "-----------"' cmd > cmd.sh; bash cmd.sh 

sed 'aXX' gắn XX để mỗi dòng. Điều này sẽ không hoạt động đối với các lệnh nhiều dòng như:

for f in * 
do 
    something $f 
fi 

nhưng đối với các lệnh một dòng trong hầu hết các trường hợp, lệnh phải thực hiện.

Các vấn đề liên quan