2011-12-28 41 views
5

Tôi có tập lệnh shell lớn hơn xử lý các thứ khác nhau.Shell Script và dấu cách trong đường dẫn

Nó sẽ nhận được đó là vị trí riêng bởi những điều sau ...

BASEDIR=`dirname $0`/.. 
BASEDIR=`(cd "$BASEDIR"; pwd)` 

sau đó basedir sẽ được sử dụng tạo ra các biến khác như

REPO="$BASEDIR"/repo 

Nhưng vấn đề là shell script này không hoạt động nếu đường dẫn chứa các khoảng trống nơi nó hiện đang được thực hiện.

Vì vậy, câu hỏi đặt ra là: Có tồn tại một giải pháp tốt để giải quyết vấn đề đó không?

+0

Những vỏ bạn đang sử dụng? – eaj

+0

Điều này nên được posix, gây ra nó nên chạy trên càng nhiều unixes càng tốt ... Ở đây bạn có thể thấy kịch bản mà tôi có nghĩa là (nó được sử dụng như là một mẫu). http://svn.codehaus.org/mojo/trunk/mojo/appassembler/appassembler-maven-plugin/src/main/resources/org/codehaus/mojo/appassembler/daemon/script/unixBinTemplate – khmarbaise

+0

Tôi đã chạy các lệnh ở trên trong cả 'bash' và' dấu gạch ngang '(những gì Ubuntu sử dụng cho 'sh'), trong một thư mục có tên thư mục cha có dấu cách. Dường như nó hoạt động tốt. Điều gì sẽ xảy ra nếu bạn chạy các lệnh từ một thiết bị đầu cuối trong một thư mục có vấn đề, theo sau là 'echo" $ REPO "'? Tôi đoán là bạn quên trích dẫn '" $ REPO "' ở đâu đó. –

Trả lời

2

Trích biến đầy đủ của bạn như thế này:

REPO="$BASEDIR/repo" 
7

Hãy chắc chắn để tăng gấp đôi-quote bất cứ điều gì có thể chứa khoảng trắng:

BASEDIR="`dirname $0`" 
BASEDIR="`(cd \"$BASEDIR\"; pwd)`" 
1

trình hoàn toàn tốt đẹp cho tôi. Bạn đang sử dụng REPO như thế nào? Điều gì đặc biệt "không hoạt động" cho bạn?

Tôi đã thử nghiệm

#!/bin/sh 
BASEDIR=`dirname $0`/.. 
BASEDIR=`(cd "$BASEDIR"; pwd)` 
REPO="$BASEDIR"/repo 
echo $REPO 

trong một ".../A b/c d" thư mục. Nó xuất ra ".../a b/repo", như mong đợi.

Vui lòng cung cấp lỗi cụ thể mà bạn đang nhận được ... Báo cáo lỗi "không hoạt động" là báo cáo lỗi hữu ích nhất và mọi lập trình viên hoàn toàn ghét nó.

1

Sử dụng dấu cách trong tên thư mục trong unix luôn là vấn đề, vì vậy nếu chúng có thể tránh được bằng cách sử dụng dấu gạch dưới, điều này ngăn chặn nhiều hành vi tập lệnh lạ.

Tôi không rõ ràng lý do tại sao bạn đang thiết basedir là thư mục cha của thư mục chứa các kịch bản hiện nay (..) và sau đó cài đặt lại nó sau khi thay đổi vào thư mục đó

Đường dẫn đến thư mục vẫn phải làm việc nếu nó có ..

ví dụ /home/trevor/data/../repo

BASEDIR=`dirname $0`/.. 

Tôi nghĩ rằng nếu bạn echo ra $ REPO nó nên có con đường giao một cách chính xác bởi vì bạn sử dụng dấu ngoặc kép khi gán cho nó nhưng nếu bạn sau đó cố gắng sử dụng $ REPO đâu đó khác trong kịch bản, bạn sẽ cần phải sử dụng dấu ngoặc kép xung quanh đó quá.

ví dụ:

#!/bin/ksh 

BASEDIR=`dirname $0`/.. 
$REPO="$BASEDIR"/repo 

if [ ! -d ["$REPO"] 
then 
    echo "$REPO does not exist!" 
fi 
1

dấu Sử dụng bài phát biểu như sau:

BASEDIR=`dirname "${0}"`/.. 
2

Không có cách nào đáng tin cậy và/hoặc cầm tay để làm điều này một cách chính xác.

Xem How do I determine the location of my script? là tại sao

Câu trả lời tốt nhất là sau đây, mà vẫn còn hệ điều hành phụ thuộc

BASEDIR=$(readlink -f $0)

Sau đó, bạn có thể làm những việc như REPO="$BASEDIR"/repo, chỉ cần chắc chắn để trích dẫn của bạn biến như bạn đã làm.

5

Câu trả lời là "Báo giá ở mọi nơi".

Nếu đường dẫn bạn vượt qua có khoảng trống trong đó dirname $0 sẽ không thành công.

$ cat quote-test.sh 
#!/bin/sh 

test_dirname_noquote() { 
     printf 'no quotes: ' 
     dirname $1 
} 
test_dirname_quote() { 
     printf 'quotes: ' 
     dirname "$1" 
} 

test_dirname_noquote '/path/to/file with spaces/in.it' 
test_dirname_quote '/path/to/file with spaces/in.it' 

$ sh quote-test.sh 
no quotes: usage: dirname string 
quotes: /path/to/file with spaces 

Ngoài ra, thử ví dụ vui nhộn này

#!/bin/sh 

mkdir -p /tmp/foo/bar/baz 
cd /tmp/foo 
ln -s bar quux 
cd quux 
cat >>find-me.sh<<"." 
#!/bin/sh 

self_dir="$(dirname $0)" 
base_dir="$((cd "$self_dir/.." ; pwd -P))" 
repo="$base_dir/repo" 

printf 'self: %s\n' "$self_dir" 
printf 'base: %s\n' "$base_dir" 
printf 'repo: %s\n' "$repo" 
. 

sh find-me.sh 

rm -rf /tmp/foo 

quả khi bạn chạy nó:

$ sh example.sh 
self: . 
base: /tmp/foo 
repo: /tmp/foo/repo 
Các vấn đề liên quan