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


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.