Shell - Ghi nội dung biến vào tệp


95

Tôi muốn sao chép nội dung của một biến (ở đây được gọi là var) vào một tệp.

Tên của tệp được lưu trữ trong một biến khác destfile.

Tôi đang gặp vấn đề khi làm việc này. Đây là những gì tôi đã thử:

cp $var $destfile

Tôi cũng đã thử điều tương tự với lệnh dd ... Rõ ràng là shell nghĩ rằng nó $varđang tham chiếu đến một thư mục và vì vậy đã nói với tôi rằng không thể tìm thấy thư mục.

Làm cách nào để giải quyết vấn đề này?


2
Vui lòng cải thiện câu hỏi của bạn bằng cách đăng một số mã được định dạng đúng cho biết cách bạn điền các biến và tất cả các thông báo lỗi có liên quan chính xác như khi chúng xuất hiện.
Todd A. Jacobs,

2
Ý bạn là gì khi "sao chép nội dung của một biến" vào một thư mục? Có $varchỉ định tên tệp hoặc một số văn bản sẽ được ghi vào tệp không? Nếu nó chỉ định văn bản, thì tên của tệp mà bạn muốn viết nội dung này là gì?
jahroy

$ var chứa văn bản mà tôi muốn được sao chép và tệp mà nó sẽ được viết vào đó là do người dùng xác định, do đó, lý do tôi đang sử dụng một biến ngay từ đầu.
user1546083 23/07/12

1
Có lẽ $destdirnên được đặt tên $destfileđể nó không gây hiểu lầm ... Cái tên $destdircho thấy nó chỉ định một thư mục hơn là một tệp. Điều này sẽ làm cho toàn bộ câu hỏi của bạn trở nên dễ hiểu và dễ hiểu.
jahroy

Câu trả lời:


145

Sử dụng echolệnh:

var="text to append";
destdir=/some/directory/path/filename

if [ -f "$destdir" ]
then 
    echo "$var" > "$destdir"
fi

Các if bài kiểm tra $destdirđại diện cho một tệp.

Các >gắn thêm các văn bản sau khi cắt bỏ các tập tin. Nếu bạn chỉ muốn nối văn bản vào $vartệp nội dung hiện có, hãy sử dụng >>thay thế:

echo "$var" >> "$destdir"

Các cplệnh được sử dụng để sao chép các file (các tập tin), chứ không phải để viết văn bản vào một tập tin.


4
Cần thêm dấu ngoặc kép - ngay bây giờ, bất kỳ chạy của khoảng trắng trong giá trị của biến sẽ được chuyển đổi sang một không gian duy nhất, biểu glob sẽ được mở rộng, vv
Charles Duffy

2
Một điều khác - bạn cần một khoảng trống giữa phần trích dẫn kết thúc và phần đầu ]vào "$destdir"].
Charles Duffy

3
echocũng thêm một dòng mới ở cuối vào biến của bạn.
Ben Dilts

6
Điều này không thành công nếu $var-e text to appendvà không thực sự viết-e
Eric

1
Bởi vì echo $var dựa vào shell để mở rộng biến của bạn, nó không hoạt động tốt với những thứ như khoảng trắng và các ký tự đặc biệt. Bạn có thể sử dụng perl -e 'print($ENV{var})'thay thế và nó sẽ xuất ra chính xác giá trị của biến.
Blake Mitchell

38

echo có vấn đề mà nếu var chứa một cái gì đó giống như -e, nó sẽ được hiểu là một lá cờ. Một tùy chọn khác là printf, nhưng printf "$var" > "$destdir"sẽ mở rộng bất kỳ ký tự thoát nào trong biến, vì vậy nếu biến chứa dấu gạch chéo ngược, nội dung tệp sẽ không khớp. Tuy nhiên, bởi vì printfchỉ diễn giải dấu gạch chéo ngược dưới dạng thoát trong chuỗi định dạng, bạn có thể sử dụng công %scụ định dạng để lưu trữ nội dung biến chính xác vào tệp đích:

printf "%s" "$var" > "$destdir"


1
printf cũng tốt nếu bạn có dòng mới trong chuỗi biến, như từ dấu ngoặc kép hoặc heredoc. echo không xử lý tốt các dòng mới.
beeflobill

@beeflobill bạn có thể giải thích làm thế nào "echo không xử lý tốt các dòng mới". Điều duy nhất tôi thấy là tiếng vọng thêm một dòng mới. Điều nào làm echo "$var" > destfilesai.
SensorSmith, 28/09/18

@SensorSmith Trong các thử nghiệm của mình, tôi thấy rằng khi chuỗi có "\ n" mà tiếng vọng sẽ in ra một ký tự dòng mới. Tuy nhiên, nếu chuỗi có một ký tự dòng mới thực sự mà echo sẽ không in nó. Tôi không biết tại sao.
beeflobill

1
Về cơ bản là một vấn đề về tính di động (và độ tin cậy). unix.stackexchange.com/a/65819… hoặc cho những người đã chết trong chúng ta: printftốt hơn hết, hãy tiếp tục.
user3342816

29

Không có câu trả lời nào ở trên hoạt động nếu biến của bạn:

  • bắt đầu với -e
  • bắt đầu với -n
  • bắt đầu với -E
  • chứa một \ theo sau bởi mộtn
  • không nên có thêm một dòng mới sau nó

và vì vậy chúng không thể được dựa vào cho nội dung chuỗi tùy ý.

Trong bash, bạn có thể sử dụng "here string" như:

cat <<< "$var" > "$destdir"

Như đã lưu ý trong nhận xét bên dưới, câu trả lời của @ Trebawa (được xây dựng trong cùng phòng với tôi!) Bằng cách sử dụng printflà một cách tiếp cận tốt hơn.


5
Từ những gì tôi có thể nói, mèo sẽ luôn chèn một dòng mới vào cuối tệp, bất kể không có dòng mới ở cuối biến (mặc dù có thể nói đây là một điều tốt trong hầu hết các trường hợp). Câu trả lời bằng cách sử dụng printf dường như tránh chèn một dòng mới ở cuối.
Ash

@Ash một lợi thế của printfhơn catlà trước đây là một BUILTIN vỏ mà sẽ luôn luôn thực hiện nhanh hơn so với một nhị phân bên ngoài.
Géza Török

7

Nếu tôi hiểu bạn đúng, bạn muốn sao chép $varvào một tệp (nếu đó là một chuỗi).

echo $var > $destdir

Đây là cách mà nó được hoàn thành. Sử dụng cplệnh sẽ làm cho trình bao diễn giải đối số đầu tiên là tên của tệp hoặc thư mục.
jahroy

5
Nếu bạn không đặt $vartrong dấu ngoặc kép, nội dung của tệp không giống 100% với nội dung của $ var trong một số trường hợp. Ví dụ: khi các vars "vọng lại" có chứa khóa RSA, bạn nhận được khóa không hợp lệ trong tệp.
srigi

6
Không thành công nếu $varchứa khoảng trắng hoặc-e
Eric

1

Khi bạn nói "sao chép nội dung của một biến", biến đó có chứa tên tệp hay không chứa tên của tệp?

Tôi giả sử câu hỏi của bạn $varcó chứa nội dung bạn muốn sao chép vào tệp:

$ echo "$var" > "$destdir"

Điều này sẽ lặp lại giá trị của $ var vào một tệp có tên là $ destdir. Lưu ý các dấu ngoặc kép. Rất quan trọng để có "$ var" được đặt trong dấu ngoặc kép. Cũng cho "$ destdir" nếu có khoảng trắng trong tên. Để nối nó:

$ echo "$var" >> "$destdir"

3
Không thành công nếu varchứa-e
Eric

1
Chuyển dấu gạch nối kép làm đối số đầu tiên để echo kết thúc danh sách tùy chọn của nó, do đó giải quyết vấn đề được nêu ra bởi @Eric:echo -- "$var" >> "$destfile"
Géza Török

1

Tất cả các công việc trên, nhưng cũng phải giải quyết một vấn đề (thoát và các ký tự đặc biệt) không cần thiết phải xảy ra ngay từ đầu: Các ký tự đặc biệt khi biến được mở rộng bởi shell. Chỉ cần không làm điều đó (mở rộng biến) ngay từ đầu. Sử dụng biến trực tiếp, không cần mở rộng.

Ngoài ra, nếu biến của bạn chứa một bí mật và bạn muốn sao chép bí mật đó vào một tệp, bạn có thể không muốn mở rộng trong dòng lệnh vì truy tìm / lặp lại lệnh của các lệnh shell có thể tiết lộ bí mật. Có nghĩa là, tất cả các câu trả lời sử dụng$var trong dòng lệnh có thể tiềm ẩn nguy cơ bảo mật bằng cách để lộ các nội dung thay đổi để truy tìm và ghi lại trình bao.

Dùng cái này:

printenv var >file

Điều đó có nghĩa là, trong trường hợp câu hỏi OP:

printenv var >"$destfile"
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.