Чи підтримує сортування сортування файлу на місці, наприклад `sed - in-place`?


80

Я сліпий чи немає такого варіанту, як --in-placeдля sort?

Для збереження результатів у вхідному файлі sed використовує -i( --in-place).

Перенаправлення виводу sortна вхідний файл

sort < f > f

призводить до того, що він порожній. Якщо немає --in-placeваріанту - можливо, є якийсь трюк, як це зробити зручним способом?

(Єдине, що впадає мені в голову:

sort < f > /tmp/f$$ ; cat /tmp/f$$ > f ; rm /tmp/f$$

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


Є також insitu, що дозволяє використовувати будь-які команди на місці.
sr_

@sr_, це цікава команда, але вона не працює з будь-якою командою, лише ті, які записують не швидше, ніж вони читають (інакше вона зменшить вхідний файл, перш ніж команда прочитає її). Немає гарантій, що це буде працювати sort.
cjm

@cjm, я дійсно не впевнений, але чи не слід це вирішувати у цій справі?
sr_

@sr_, я думаю, ти маєш рацію. Я читаю опис, а не дивлюсь на джерело. Хоча для справді великих файлів у буфера може не вистачати пам'яті та вийти з ладу (це не схоже на те, що він перевіряє повернення NULL з malloc).
cjm

@cjm: О так, справді.
sr_

Відповіді:


110

sortмає -o, --outputопцію, яка приймає ім'я файлу як аргумент. Якщо він такий самий, як і вхідний файл, він записує результат у тимчасовий файл, а потім перезаписує вихідний вхідний файл (точно те саме, що sed -iробить).

З GNU sortінформаційної сторінки:

`-o OUTPUT-FILE'
`--output=OUTPUT-FILE'
      Write output to OUTPUT-FILE instead of standard output.  Normally,
      `sort' reads all input before opening OUTPUT-FILE, so you can
      safely sort a file in place by using commands like `sort -o F F'
      and `cat F | sort -o F'.  However, `sort' with `--merge' (`-m')
      can open the output file before reading all input, so a command
      like `cat F | sort -m -o F - G' is not safe as `sort' might start
      writing `F' before `cat' is done reading it.

      On newer systems, `-o' cannot appear after an input file if
      `POSIXLY_CORRECT' is set, e.g., `sort F -o F'.  Portable scripts
      should specify `-o OUTPUT-FILE' before any input files.

та з Технічних характеристик бази відкритих груп, випуск 7 :

-o  output
    Specify the name of an output file to be used instead of the standard 
    output. This file can be the same as one of the input files.

Саме так! Це працює ! Я не бачу жодної підказки про це man sort- це недокументована функція? Це стандартно і портативно?
Grzegorz Wierzowiecki

@GrzegorzWierzowiecki: див. Оновлення.
enzotib

Приємна відповідь :).
Grzegorz Wierzowiecki

1
Підсумовуючи: sort -o <filename> <filename>безпечно сортувати файл на місці.
фіат

11

Ви можете використовувати spongeфункцію, яка спочатку замочує, stdinа потім записує її у файл, наприклад:

sort < f | sponge f

Недоліком цього spongeє те, що він буде зберігати вихідний тимчасовий у пам'яті, що може бути проблематично для великих файлів. В іншому випадку потрібно спершу записати його у файл, а потім перезаписати вихідний файл.

Як вказують інші відповіді, зміни на місці взагалі не є гарною ідеєю, оскільки в середині процесу (наприклад, spongeодного) машина може вийти з ладу, і тоді ви можете втратити і вихідний, і новий файл. Вам краще спочатку записати його в інший файл, а потім скористатися атомною mv(переміщенням) інструкцією.


7

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

Кілька програм (переважно версії GNU) мають можливість встановити місце (наприклад, -iна perl та GNU sed; -oдля GNU сортування). Вони працюють, поміщаючи дані у тимчасовий файл, а потім переміщуючи їх на місце. Для програм , які не мають такої варіанта, Колін Уотсон spongeутиліта (входить в moreutils Джой Гесса ) робить роботу безпечно для будь-якої програми (приклади: Можемо чи я зробити cut? Змінити файл на місці , як я можу зробити Iconv замінити вхідний файл з перетвореним вихід? ).

Лише в тих рідкісних випадках, коли ви не можете відтворити оригінальний файл з однаковими дозволами, рекомендую перезаписати файл на місце. У цьому випадку вам краще зберегти оригінальний запис десь. І тоді ви можете просто обробити копію вводу та надіслати її у вихідний файл.

cp -p f ~/f.backup
sort <~/f.backup >|f
rm ~/f.backup # optional

1
sort -oне є специфічним для GNU, і спеціально розроблений для перенаправлення файлу на місці. sortне може почати запис свого виводу до того, як він повністю прочитає свої входи (використовує пам'ять або тимчасові файли для зберігання даних), тому цілком природно, що він повинен мати змогу змінити свій вхід.
Стефан Шазелас

Насправді, це один випадок, коли GNU sortне є POSIX, оскільки sort -mo file1 file1 file2він не гарантовано працює, в той час як традиційні sortзнають, як обійти це питання (вже в 70-х роках Unix V7).
Стефан Шазелас

@JoelCross Odd, sort -oпрацює для мене з coreutils 8.25, а властивість задокументована в посібнику (зауваживши, що це стосується лише сортування, а не при злитті). Якщо ви зможете відтворити це, надішліть звіт про помилку (із зазначенням точного командного рядка, точних вхідних файлів (файлів), в якій системі ви працюєте та як ви отримали двійковий файл).
Жиль

4

Скористайтеся -oабо спробуйте vim-way:

$ ex -s +'%!sort' -cxa file.txt
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.