Оболонка - запис вмісту змінної у файл


95

Я хотів би скопіювати вміст змінної (яку тут називають var) у файл.

Ім'я файлу зберігається в іншій змінній destfile.

У мене проблеми з цим. Ось що я спробував:

cp $var $destfile

Я теж пробував те саме з командою dd ... Очевидно, оболонка думала, що $varйдеться про каталог, і тому сказала мені, що каталог неможливо знайти.

Як я можу обійти це?


2
Будь ласка, вдосконаліть своє запитання, опублікувавши якийсь правильно відформатований код, який показує, як ви заповнюєте свої змінні, та всі відповідні повідомлення про помилки точно такими, як вони з'являються.
Тодд А. Джейкобс

2
Що ви маєте на увазі під словом "скопіювати вміст змінної" в каталог? Чи $varвказано ім'я файлу чи текст, який слід записати у файл? Якщо він вказує текст, то як називається файл, до якого ви хочете написати цей вміст?
jahroy

$ var містить текст, який я хочу скопіювати, і файл, до якого він повинен бути записаний, визначається користувачем, отже, причина того, що я спочатку використовую змінну.
user1546083

1
Можливо, його $destdirслід назвати, $destfileщоб це не вводило в оману ... З назви $destdirвипливає, що воно вказує каталог, а не файл. Це зробить все ваше запитання простим і простим для розуміння.
jahroy

Відповіді:


145

Використовуйте echoкоманду:

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

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

У ifтестах , які $destdirпредставляють файл.

>Додає текст після усічення файлу. Якщо ви хочете лише додати текст $varдо наявного вмісту файлу, використовуйте >>замість цього:

echo "$var" >> "$destdir"

cpКоманда використовується для копіювання файлів (в файли), а не для введення тексту в файл.


4
Потрібні більше лапок - прямо зараз, будь-які пробіли в межах значення змінної будуть перетворені в єдиний пробіл, вирази глобуса будуть розширені тощо
Чарльз Даффі

2
Ще одна річ - вам потрібен пробіл між кінцевою цитатою та ]входом "$destdir"].
Чарльз Даффі

3
echoтакож додає кінцевий новий рядок до вашої змінної.
Бен Ділтс,

6
Це не вдається, якщо $varє -e text to append, і насправді не пише-e
Ерік,

1
Оскільки echo $varпокладатися на оболонку для розширення вашої змінної, це не дуже добре працює з такими речами, як пробіли та спеціальні символи. Ви можете використовувати perl -e 'print($ENV{var})'замість цього, і воно точно виведе значення змінної.
Блейк Мітчелл,

38

echoмає проблему, що якщо вона varмістить щось на зразок -e, це буде інтерпретовано як прапор. Іншим варіантом є printf, але printf "$var" > "$destdir"він розширить будь-які екрановані символи у змінній, тому якщо змінна містить зворотні слеші, вміст файлу не збігатиметься. Однак оскільки printfінтерпретує зворотні скісні риски як символи екрану у рядку формату, ви можете використовувати %sспецифікатор формату для зберігання точного змісту змінної у цільовому файлі:

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


1
printf також хороший, якщо у вас є нові рядки у змінній рядок, наприклад, з потрійної лапки або heredoc. echo погано справляється з новими рядками.
beeflobill

@beeflobill можете пояснити, як "echo погано справляється з новими рядками". Єдине, що я бачив, це те, що луна додає новий рядок. Що робить echo "$var" > destfileнеправильно.
SensorSmith

@SensorSmith У своїх експериментах я бачу, що коли рядок має "\ n", це луна надрукує символ нового рядка. Але якщо рядок має фактичний символ нового рядка, то луна його не надрукує. Не знаю чому.
beeflobill

1
В основному проблема переносимості (та надійності). unix.stackexchange.com/a/65819 ... або для смертельних серед нас: printfкраще, рухайтесь далі.
користувач3342816

29

Жодна з наведених відповідей не працює, якщо ваша змінна:

  • починається з -e
  • починається з -n
  • починається з -E
  • містить a \ наступне за символомn
  • не повинен мати додаткового нового рядка, доданого після нього

і тому на них не можна покладатися на довільний вміст рядка.

У bash ви можете використовувати "тут рядки" як:

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

Як зазначено у коментарі нижче, відповідь @ Trebawa (сформульована в тій самій кімнаті, що і моя!), printfЄ кращим підходом.


5
З того, що я можу сказати, cat завжди буде вставляти новий рядок в кінці файлу, незалежно від того, що в кінці змінної немає нового рядка (хоча, можливо, це добре в більшості випадків). З допомогою Printf відповіді , здається , щоб уникнути вставок завершального символу нового рядка.
Еш

Ще однією перевагою printfнад catє те, що перший - це вбудована оболонка, яка завжди буде виконуватися швидше, ніж зовнішній двійковий файл.
Géza Török

7

Якщо я правильно вас зрозумів, ви хочете скопіювати $varу файл (якщо це рядок).

echo $var > $destdir

Ось як це робиться. Використання cpкоманди змусить оболонку інтерпретувати перший аргумент як ім'я файлу або каталогу.
jahroy

5
Якщо ви не вкладаєте $varв лапки, вміст файлу не на 100% дорівнює вмісту $ var в деяких випадках. Наприклад, коли "лунає" var, що містить ключі RSA, ви отримуєте недійсний ключ у файлі.
srigi

6
Не вдається, якщо $varмістить пробіли або-e
Ерік,

1

Коли ви говорите "скопіювати вміст змінної", чи містить ця змінна ім'я файлу чи воно містить ім'я файлу?

Я припускаю, що за вашим запитанням, що $varмістить вміст, який ви хочете скопіювати у файл:

$ echo "$var" > "$destdir"

Це відобразить значення $ var у файлі, який називається $ destdir. Зверніть увагу на цитати. Дуже важливо, щоб "$ var" було в лапках. Також для "$ destdir", якщо в назві є пробіл. Щоб додати його:

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

3
Не вдається, якщо varмістить-e
Ерік

1
Передача подвійного дефісу як першого аргументу для echo припинення його списку варіантів, таким чином, вирішує проблему, порушену @Eric:echo -- "$var" >> "$destfile"
Геза Терек

1

Усе вищезазначене працює, але також має вирішити проблему (екрани та спеціальні символи), яка не повинна виникати в першу чергу: Спеціальні символи, коли змінна розширюється оболонкою. Просто не робіть цього (змінне розширення) спочатку. Використовуйте змінну безпосередньо, без розширення.

Крім того, якщо ваша змінна містить секрет, і ви хочете скопіювати цей секрет у файл, можливо, ви захочете не мати розширення в командному рядку, оскільки трасування / ехо команд команд оболонки може розкрити секрет. Значить, усі відповіді, які використовуються$var в командному рядку, можуть мати потенційний ризик безпеки, піддаючи зміст змінного відстеженню та реєстрації оболонки.

Використовуй це:

printenv var >file

Це означає, що у разі запитання про ОП:

printenv var >"$destfile"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.