Shell - Menulis konten variabel ke file

98

Saya ingin menyalin konten variabel (di sini disebut var) ke dalam file.

Nama file disimpan di variabel lain destfile.

Saya mengalami masalah saat melakukan ini. Inilah yang saya coba:

cp $var $destfile

Saya juga mencoba hal yang sama dengan perintah dd ... Jelas shell mengira yang $varmerujuk ke direktori dan memberi tahu saya bahwa direktori tidak dapat ditemukan.

Bagaimana cara menyiasati ini?

pengguna1546083
sumber
2
Harap perbaiki pertanyaan Anda dengan memposting beberapa kode yang diformat dengan benar yang menunjukkan bagaimana Anda mengisi variabel Anda, dan semua pesan kesalahan yang relevan persis seperti yang muncul.
Todd A. Jacobs
2
Apa yang Anda maksud dengan "menyalin konten variabel" ke direktori? Apakah $varmenentukan nama file atau beberapa teks yang harus ditulis ke file? Jika itu menentukan teks, lalu apa nama file yang Anda inginkan untuk menulis konten ini?
jahroy
$ var berisi teks yang ingin saya salin dan file yang harus dituliskan adalah yang ditentukan oleh pengguna, oleh karena itu alasan saya menggunakan variabel di tempat pertama.
pengguna1546083
1
Mungkin $destdirharus diberi nama $destfileagar tidak menyesatkan ... Namanya $destdirmenyarankan itu menentukan direktori daripada file. Ini akan membuat seluruh pertanyaan Anda lugas dan mudah dimengerti.
jahroy

Jawaban:

149

Gunakan echoperintah:

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

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

The iftes yang $destdirmewakili file.

The >menambahkan teks setelah truncating file. Jika Anda hanya ingin menambahkan teks $varke file konten yang ada, gunakan >>sebagai gantinya:

echo "$var" >> "$destdir"

The cpPerintah ini digunakan untuk menyalin file (file), bukan untuk menulis teks ke file.

pb2q
sumber
4
Membutuhkan lebih banyak tanda kutip - sekarang, setiap spasi kosong dalam nilai variabel akan dikonversi ke satu spasi, ekspresi glob akan diperluas, dll.
Charles Duffy
2
Satu hal lagi - Anda membutuhkan spasi antara kutipan penutup dan ]dalam "$destdir"].
Charles Duffy
3
echojuga menambahkan baris baru trailing ke variabel Anda.
Ben Dilts
6
Ini gagal jika $varada -e text to append, dan tidak benar-benar menulis-e
Eric
1
Karena echo $varmengandalkan shell untuk memperluas variabel Anda, itu tidak akan berfungsi dengan baik dengan hal-hal seperti spasi dan karakter khusus. Anda dapat menggunakan perl -e 'print($ENV{var})'sebagai gantinya, dan itu akan menghasilkan nilai variabel dengan tepat.
Blake Mitchell
41

echomemiliki masalah jika varmengandung sesuatu seperti -e, itu akan diartikan sebagai sebuah bendera. Opsi lainnya adalah printf, tetapi printf "$var" > "$destdir"akan memperluas karakter yang lolos dalam variabel, jadi jika variabel berisi garis miring terbalik, konten file tidak akan cocok. Namun, karena printfhanya menafsirkan garis miring terbalik sebagai pelarian dalam format string, Anda dapat menggunakan %spenentu format untuk menyimpan konten variabel yang tepat ke file tujuan:

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

Trebawa
sumber
1
printf juga bagus jika Anda memiliki baris baru dalam string variabel, seperti dari kutipan tiga atau heredoc. echo tidak menangani baris baru dengan baik.
beeflobill
@beeflobill dapatkah Anda menjelaskan bagaimana "echo tidak menangani baris baru dengan baik". Satu-satunya hal yang saya lihat adalah gema menambahkan baris baru. Yang mana yang echo "$var" > destfilesalah.
SensorSmith
@SensorSmith Dalam eksperimen saya, saya melihat bahwa ketika string memiliki "\ n", gema itu akan mencetak karakter baris baru. Tetapi, jika string memiliki karakter baris baru yang sebenarnya, echo tidak akan mencetaknya. Saya tidak tahu kenapa.
beeflobill
1
Pada dasarnya masalah portabilitas (dan keandalan). unix.stackexchange.com/a/65819… atau untuk yang mematikan di antara kita: printflebih baik, lanjutkan.
pengguna3342816
30

Tidak ada jawaban di atas yang berfungsi jika variabel Anda:

  • dimulai dengan -e
  • dimulai dengan -n
  • dimulai dengan -E
  • berisi yang \diikuti dengann
  • seharusnya tidak ada baris baru tambahan yang ditambahkan setelahnya

dan karenanya tidak dapat diandalkan untuk konten string yang berubah-ubah.

Di bash, Anda dapat menggunakan "string di sini" sebagai:

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

Seperti yang tertulis di komentar di bawah, jawaban @ Trebawa (diformulasikan di ruangan yang sama dengan saya!) Menggunakan printfpendekatan yang lebih baik.

Eric
sumber
5
Dari apa yang saya tahu, cat akan selalu menyisipkan baris baru di akhir file, terlepas dari tidak ada baris baru di akhir variabel (walaupun bisa dibilang ini adalah hal yang baik dalam banyak kasus). The jawaban menggunakan printf tampaknya untuk menghindari memasukkan baris baru trailing.
Ash
@Ash Keuntungan lain dari printfover catadalah bahwa yang pertama adalah shell bawaan yang akan selalu dieksekusi lebih cepat daripada biner eksternal.
Géza Török
7

Jika saya mengerti Anda benar, Anda ingin menyalin $vardalam file (jika itu adalah string).

echo $var > $destdir
qwertz.dll
sumber
Beginilah cara melakukannya. Menggunakan cpperintah akan membuat shell menafsirkan argumen pertama sebagai nama file atau direktori.
jahroy
5
Jika Anda tidak menyertakan $vartanda kutip, konten file tidak 100% sama dengan konten $ var dalam beberapa kasus. Misalnya ketika "echoing" vars yang berisi kunci RSA, Anda mendapatkan kunci yang tidak valid di file.
srigi
6
Gagal jika $varberisi spasi atau-e
Eric
1

Ketika Anda mengatakan "salin konten variabel", apakah variabel itu berisi nama file, atau apakah itu berisi nama file?

Saya berasumsi dengan pertanyaan Anda yang $varberisi konten yang ingin Anda salin ke dalam file:

$ echo "$var" > "$destdir"

Ini akan menggemakan nilai $ var ke dalam file bernama $ destdir. Perhatikan kutipannya. Sangat penting untuk menyertakan "$ var" di dalam tanda kutip. Juga untuk "$ destdir" jika ada spasi di namanya. Untuk menambahkannya:

$ echo "$var" >> "$destdir"
David W.
sumber
3
Gagal jika varmengandung-e
Eric
1
Meneruskan tanda hubung ganda sebagai argumen pertama untuk echo mengakhiri daftar opsinya, dengan demikian menyelesaikan masalah yang diangkat oleh @Eric:echo -- "$var" >> "$destfile"
Géza Török
1

Semua pekerjaan di atas, tetapi juga harus mengatasi masalah (pelarian dan karakter khusus) yang tidak perlu terjadi di tempat pertama: Karakter khusus ketika variabel diperluas oleh shell. Jangan lakukan itu (ekspansi variabel) di tempat pertama. Gunakan variabel secara langsung, tanpa ekspansi.

Selain itu, jika variabel Anda berisi sebuah rahasia dan Anda ingin menyalin rahasia itu ke dalam sebuah file, Anda mungkin ingin tidak memiliki ekspansi di baris perintah karena tracing / perintah gema dari perintah shell mungkin mengungkapkan rahasianya. Artinya, semua jawaban yang digunakan $vardalam baris perintah mungkin memiliki potensi risiko keamanan dengan mengekspos konten variabel ke penelusuran dan pencatatan shell.

Gunakan ini:

printenv var >file

Artinya, jika ada pertanyaan OP:

printenv var >"$destfile"
Christian Hujer
sumber