Сортировка всех файлов в папке независимо, с выходным файлом для каждого

326
Hashim

У меня есть несколько папок, которые содержат множество текстовых файлов, от десятков до сотен. Эти текстовые файлы представляют собой простые базы данных, содержащие миллионы строк, причем каждая строка содержит одну запись. Однако записи в них не отсортированы и содержат много дубликатов. Я хотел бы отсортировать и дедуплицировать их все по отдельности (т.е. независимо друг от друга), но, насколько я понимаю, sortможет производить только каскадный вывод всех входных файлов - то есть, даже если дано несколько файлов, он будет только создать один выходной файл, содержащий объединенные результаты всех этих файлов.

Как я могу отсортировать все файлы в текущей папке, чтобы получить индивидуально отсортированный выходной файл для каждого ? Я также хотел бы, чтобы выходные файлы выводились во вложенную папку в текущем каталоге. forПетля является очевидным решением для меня, но я спрашиваю здесь, в случае, если есть какой - то простой способ сделать это с, sortчто я не сталкивался или пропустил. Моим bashзнаниям также очень не хватает, поэтому, если forцикл - самое простое решение, я был бы признателен за то, что кто-то предоставил бы лучший способ добиться этого, вместо того, чтобы тратить много дней на то, чтобы взломать что-то вместе, что все равно не соответствует тому, что я хочу сделать.

0
`sort -u` предоставляет один список записей. matzeri 6 лет назад 0
@matzeri Ты троллинг? Hashim 6 лет назад 0

1 ответ на вопрос

1
Kamil Maciorowski

Да, вы можете сделать это с for. Даже если есть «какой-то более простой способ сделать это sort» (но я так не думаю), это также довольно просто:

# cd to the directory you want to process  mkdir sorted  for file in *;  do printf 'Processing %s\n' "$file" [ -f "$file" ] && sort -u "$file" > "./sorted/$file" done 

Заметки:

  • for file in * не обрабатывает файлы в подкаталогах.
  • printfтолько сообщить о прогрессе. Фактически это должно быть размещено после [ ... ](см. Ниже), но я не хочу слишком усложнять код. Вы можете просто удалить printfстроку, если хотите, чтобы все это было тихим.
  • [ -f "$file" ]проверяет, $fileявляется ли обычный файл. С наиболее общим шаблоном (то есть *) нам нужно это условие по крайней мере, чтобы избежать работы sortс sortedкаталогом в качестве аргумента (это приведет к ошибке, безвредной, но не элегантной). Скорее всего, этот тест не понадобится, если вы используете более конкретный глобус, например *.txtили *.dbвместо *(например, для пропуска случайного desktop.iniфайла, который не должен обрабатываться). В этом случае вы можете опустить [ ... ] &&и начать строку с sort(оставляя линию нетронутой, однако, не повредит).
  • sort поддерживает различные варианты, и вы можете использовать некоторые из них, в зависимости от того, как вам нужно сортировать.

  • sort -uДедуплицирует записи сразу после их сортировки и, когда они уже используются, sortявляется менее излишней альтернативой использованию uniqкоманды.

Если вам нужно выбрать файлы в соответствии с более сложными условиями, чем простой глобус, findлучше начать с этого. Для вашей текущей задачи forдолжно быть хорошо.

Это выглядит идеально, большое спасибо. Есть часть кода, в которой я немного запутался - откуда взялся `[-f" $ file "]`? То есть, к какой команде относится параметр `-f`, и что именно означают квадратные скобки? Я не видел такой синтаксис, используемый в bash-файле раньше, по крайней мере, не в этом контексте. Hashim 6 лет назад 0
Хорошо, я нашел свой ответ здесь, что он синонимичен команде `test`: https://stackoverflow.com/questions/28036052/what-does-f-mea, но для пояснения, что именно это означает? Что `[...]` является сокращением для команды test? Hashim 6 лет назад 0
@Hashim Смотрите `help [` в Bash. Kamil Maciorowski 6 лет назад 0
Unfortunately that doesn't give any information other than saying it's a synonym, so I suppose that's the only answer. There is one more thing - I've become accustomed to doing `LC_ALL=C sort` to make what usually be a ridiculously slow `sort` command a lot faster by limiting it to the default (US English) locale. Do you know of any way to incorporate that into your code above? Simply adding it before `sort` as normal results in a `syntax error near unexpected token &&`. It's not a major problem if it can't be done, but it would be nice to find out whether it can be. Hashim 6 лет назад 0
Кроме того, я надеюсь, что вы не возражаете, но я внес небольшие исправления в код, которые, по моему мнению, сделали его немного менее избыточным, не стесняйтесь отменить их, если была причина, по которой вы изначально его кодировали. Hashim 6 лет назад 0
@Hashim `[ -f "$file" ] && LC_ALL=C sort …` works for me on Debian. Kamil Maciorowski 6 лет назад 0
Nevermind, I was being slightly dense. Had decided to take out the file test command but had forgotten what you said about starting the line with sort. That gave me the following: https://pastebin.com/hxs9xNBm. I suppose I assumed that the `&&` would chain on from the `printf` command just like it did with the file test command. Is there a reason this isn't the case? Hashim 6 лет назад 0
@Hashim Yes. When the shell parses `printf`, it has no reason to look forward to the next line. When the shell encounters your `&&`, the line with `printf` has already been parsed and executed. Kamil Maciorowski 6 лет назад 1
Ah I see, that makes sense. Sorry to keep bothering you with this but I promise this is the last question I'll ask for this piece of code. :P I've been trying to figure out how to modify the code in question to output the sorted file in the same directory, but with a `_sorted` suffix at the end of it. Is that a lot harder to do? I can't seem to find any help for it elsewhere hence why I'm still bothering you. So far I have `LC_ALL=C sort -u "$i" >> "./$i_sorted"`, but for some reason that stops with `Is a directory` errors even though it looks to me like a file and there is no such directory. Hashim 6 лет назад 0
Давайте [продолжим это обсуждение в чате] (https://chat.stackexchange.com/rooms/83138/discussion-between-kamil-maciorowski-and-hashim). Kamil Maciorowski 6 лет назад 0

Похожие вопросы