Unix как IDE: Файлы

http://blog.sanctum.geek.nz/unix-as-ide-files/
  • Перевод
Одной из важных особенностей IDE является встроенная система управления файлами. Она должна включать в себя как базовые возможности, такие как переименование, удаление перемещение, так и более специфические для разработки: компиляция и проверка синтаксиса. Вдобавок было бы удобно оперировать группами файлов для поиска по размеру, расширению или по маске. В этой первой статье я покажу несколько вариантов использования инструментов, знакомых любому пользователю Linux, для работы с группами файлов в проекте.


Списки файлов


Администратор знакомится с командой ls одной из первых, чтобы с ее помощью просматривать простой список содержимого директории. Многие администраторы также умеют использовать ключи -a и -l, чтобы вывести все файлы, включая '.' и '..', и чтобы отобразить более детальные сведения о файлах по колонкам, соответственно.

Существует еще несколько ключей для ls, несколько реже используемых, но очень полезных для целей программирования:
  • -t — Вывести файлы, выстроенные по дате последней модификации в порядке убывания. Ключ полезен для очень больших директорий, когда нужно быстро получить список самых последних отредактированных файлов, возможно пропущенных через head или sed 10q. Наверное, наиболее полезен в связке с -l. Если нужны самые старые файлы, можно добавить -r и тем самым перестроить список в обратном порядке.
  • -X — Группировать файлы по расширению. Полезно для многоязычной разработки, для отделения заголовочных файлов от основного кода, для отделения файлов кода от директорий или от сборочных файлов.
  • -v — Позволяет легко сортировать номера версий в именах файлов.
  • -S — Сортировка по размеру файла.
  • -R — Вывести список файлов рекурсивно, включая подкаталоги. Этот ключ хорош в связке с -l и перенаправлением вывода на постраничную листалку вроде less.


Поскольку список файлов — это обычный текст, можно направить его поток в vim, где добавить пояснения к каждому файлу, а потом сохранить текст в качестве описи или добавить в README:

$ ls -XR | vim -


Подобные вещи даже могут быть автоматизированы при помощи make без особых усилий, о чем я расскажу в другой статье из этой серии.

Поиск файлов


Как ни странно, можно получить полный список файлов, включая относительные пути, просто напечатав "find" без аргументов, хотя обычно лучше выстроить их по порядку при помощи sort:

$ find | sort

.
./Makefile
./README
./build
./client.c
./client.h
./common.h
./project.c
./server.c
./server.h
./tests
./tests/suite1.pl
./tests/suite2.pl
./tests/suite3.pl
./tests/suite4.pl


Если хотите вывести файлы подобно ls, можно добавить -ls:

$ find -ls | sort -k 11
1155096    4 drwxr-xr-x   4 tom      tom          4096 Feb 10 09:37 .
1155152    4 drwxr-xr-x   2 tom      tom          4096 Feb 10 09:17 ./build
1155155    4 -rw-r--r--   1 tom      tom          2290 Jan 11 07:21 ./client.c
1155157    4 -rw-r--r--   1 tom      tom          1871 Jan 11 16:41 ./client.h
1155159   32 -rw-r--r--   1 tom      tom         30390 Jan 10 15:29 ./common.h
1155153   24 -rw-r--r--   1 tom      tom         21170 Jan 11 05:43 ./Makefile
1155154   16 -rw-r--r--   1 tom      tom         13966 Jan 14 07:39 ./project.c
1155080   28 -rw-r--r--   1 tom      tom         25840 Jan 15 22:28 ./README
1155156   32 -rw-r--r--   1 tom      tom         31124 Jan 11 02:34 ./server.c
1155158    4 -rw-r--r--   1 tom      tom          3599 Jan 16 05:27 ./server.h
1155160    4 drwxr-xr-x   2 tom      tom          4096 Feb 10 09:29 ./tests
1155161    4 -rw-r--r--   1 tom      tom           288 Jan 13 03:04 ./tests/suite1.pl
1155162    4 -rw-r--r--   1 tom      tom          1792 Jan 13 10:06 ./tests/suite2.pl
1155163    4 -rw-r--r--   1 tom      tom           112 Jan  9 23:42 ./tests/suite3.pl
1155164    4 -rw-r--r--   1 tom      tom           144 Jan 15 02:10 ./tests/suite4.pl



Заметьте, в данном случае мне пришлось дать указание сортировать по 11 колонке вывода, то есть по именам файлов; для этого используется ключ -k.

У find довольно сложный синтаксис встроенного фильтра. Следующие примеры показывают несколько самых полезных, которые можно применять для получения нужного списка файлов:
  • find -name '*.c' — найти файлы с именами согласно маске в стиле shell. Можно использовать -iname для регистронезависимого поиска.
  • find -path '*test*' — найти файлы, путь к которым совпадает с маской. Можно использовать -ipath для регистронезависимого поиска.
  • find -mtime -5 — найти файлы, отредактированные за последние 5 дней. Можно использовать +5 чтобы найти файлы, измененные раньше, чем 5 дней назад.
  • find -newer server.c — найти файлы, измененные раньше, чем server.c.
  • find -type d — найти директории. Для поиска файлов используется -type f; для символических ссылок -type l


Все вышеперечисленное можно комбинировать. Например, чтобы найти исходники на C, отредактированные за последние 2 дня, пишем:

$ find -name '*.c' -mtime -2

Над найденными файлами find может выполнять разные действия. По умолчанию это направление списка в стандартный поток вывода, но есть несколько других вариантов:
  • -ls — Выдать список в стиле ls -l.
  • -delete — Удалить найденные файлы.
  • -exec — Выполнить произвольную командную строку над каждым файлом, где {} будет заменено на соответствующее имя файла, и признаком окончания которой служит \;, например:
    $ find -name '*.pl' -exec perl -c {} \;
    

    В большинстве случаев проще применить xargs, чтобы результат превратился в аргументы для команды:
    $ find -name '*.pl' | xargs perl -c
    

  • -print0 — если у вас есть файлы с пробелами в именах, и вы хотите передать их в xargs подобно предыдущему примеру, то используйте этот ключ, и разделителем записей будет назначен 0-символ вместо пробела. Одновременно с этим xargs должен запускаться с ключом -0:
    $ find -name '*.jpg' -print0 | xargs -0 jpegoptim
    


    Я часто пользуюсь следующим трюком для генерации списков, которые затем можно редактировать в окнах Vim, делящих экран по вертикали:

    $ vim -O $(find . -name '*.c')


Иной поиск файлов



И все же гораздо чаще, чем по внешним атрибутам, требуется искать файлы, опираясь на их содержимое, и здесь grep, а особенно grep -R, спешит на помощь. Эта команда рекурсивно ищет в текущей директории все, что совпадает с указанным текстом:

$ grep -FR 'someVar' .


Не забывайте флаг регистронезависимости, поскольку по умолчанию grep работает с учетом регистра.

$ grep -iR 'somevar' .


Можно также вывести список файлов, содержащих совпадения, без самих совпадающих строк при помощи grep -l. Это, опять же, удобно при построении списка файлов для дальнейшего редактирования в текстовом редакторе:

$ vim -O $(grep -lR 'somevar' .)


Если в проекте используется контроль версий, то все метаданные обычно содержатся в папках .svn, .git или .hg. Можно без труда исключить (grep -v) ненужные элементы при помощи сравнения с фиксированной строкой (grep -F):
$ grep -R 'someVar' . | grep -vF '.svn'

Существует очень популярная альтернатива grep, именуемая ack, которая по умолчанию исключает всю подобную шелуху. Ack также позволяет использовать Perl-совместимые регулярные выражения (PCRE), столь любимые многими хакерами. Она располагает очень удобными средствами работы с исходниками. Несмотря на то, что со старым добрым grep нет никаких проблем, поскольку он всегда под рукой, при возможности очень советую установить Ack. Для всех популярных Unix-систем есть соответствующий пакет в стандартных репозиториях.

Принципиальные поклонники Unix, скорее всего, огорчены упоминанием такой сравнительно новой альтернативы grep, да еще и в виде Perl-скрипта. Однако мне не хотелось бы думать, что философия Unix и, в частности, идея использования Unix как IDE обязательно означает отказ от близких по духу современных альтернатив, способных решать актуальные проблемы.

Метаданные файлов



Утилита file выводит одной строкой сводную информацию о файле на основе расширения, заголовков и других признаков. Это очень удобно при совместном использовании с find и xargs для изучения групп незнакомых файлов:
$ find | xargs file
.:            directory
./hanoi:      Perl script, ASCII text executable
./.hanoi.swp: Vim swap file, version 7.3
./factorial:  Perl script, ASCII text executable
./bits.c:     C source, ASCII text
./bits:       ELF 32-bit LSB executable, Intel 80386, version ...

Поиск по шаблону


В заключения данной заметки, я бы советовал познакомиться поближе с поиском по шаблону и раскрытием скобок Bash. Этому вопросу посвящена моя отдельная статья.

Все вышеперечисленное наделяет оболочку Unix довольно мощными средствами управления файлами при написании программ.

Продолжение следует...

Unix как IDE: Введение
Unix как IDE: Файлы
Unix как IDE: Работа с текстом
Unix как IDE: Компиляция
Поделиться публикацией

Похожие публикации

Комментарии 35

    +13
    Еще одна статья про ls?
      0
      Под OS X некоторые команды не работают. Например, ls -X или find без аргументов. Видимо, версии GNU и BSD несколько отличаются.
        +3
        В BSD достаточно указать директорию для поиска, то есть минимально будет так:
        find .
          +1
          Аха, или поставить busybox. Или GNU findutils. Что угодно, только не ущербный bsd-шный find :).
        –1
        Консоль мощнее, но для повседневной работы эта мощь, имхо, излишня, а простоты IDE не хватает. Предпочитаю IDE, а консоль в качестве вспомогательного средства, прежде всего для работы с vcs.
          –1
          Нет нет нет и ещё раз нет.
          Вы просто не понимаете что может дать консоль. И, впрочем, никогда не сможете понять если относитесь к этому с такими взглядами. Известно, что в консольке работает гигантское количество людей. И хотя бы один этот факт должен говорить о том, что в чем-то вы заблуждаетесь.
            0
            Я тоже только в ней могу работать при необходимости. Могу в ней делать всё то же самое, что и в IDE. Но это медленнее. Вот нужно мне сейчас файл отредактировать. В IDE я его открыл за 4 одинарных клика и 1 двойной, в консоли — 16 нажатий клавиш. И это при условии, что путь к файлу из корня проекта помню наизусть, на самом деле их было больше, несколько лишних нажатий Tab чтобы получить список вариантов, плюс перевод взгляда с рук на экран и обратно. Собственно отсутствие постоянной обратной визуальной связи, плюс постоянная необходимость набирать то, что уже видишь на экране (вместо того чтобы кликнуть мышкой) и замедляет постоянно работу.

            И, вроде бы, с GUI работает куда большее число людей, архигигантское получается. Вы считаете, что все они заблуждаются?
              +3
              Обычных программистов больше ведь, чем лучших). Это я про «архигигантское».

              Конечно все написаное мной справедливо, если:

              1) слепой метод печати
              2) хотя бы 220-250 символов в минуту (у меня ~450, программистских (с запятыми, кавычками, слешами и тп)). Клавогонки и все такое). Даже при 16 символах в секунду, ваши нажатия все в 1 секунду уложаться. 4 клика мышкой, учитывая что к ней надо тянуться и между кликами двигать — будут дольше.
              3) vim /etc/cron.d/somefile => vim /e/c/somefile. Так умеет, например, zsh. Это не просто экономия на нажатиях табов, в /etc может быть несколько папок начинающихся с «c», но zsh автоматически возьмёт cron.d, при условии что somefile есть только там.

              Работа с консолью со временем становится все быстрее и быстрее и быстрее.

              По поводу п1 стоит отдельно заметить, что т.к. это вообще полезное умение при работе связанной с программированием, то его при работе с консолью навык работать с клавиатурой целиком вслепую придет быстрее =).

              Не понтов ради, но сейчас для меня необходимость тянуться к мышке иногда уже является сильным замедляющим фактором. Хотя я ничего специально нигде не пытаюсь ускорять в своём workflow. Просто с течением времени все само собой так получается.

              Ну и последнее замечание — открытие нужного файла в консоли — никто же не говорит, что это не может быть аналог GUI, но в текстовом варианте. У меня в виме есть возможность открывать файлы через встроенный файл-менеджер (ну типа :e folder/file.txt — напрямую, а если :e folder, то потом нужно лишь файл выбрать в списке). Действительно бывает удобно какие-то файлы выбирать, а не печатать. И никто не говорит тут о том чтобы бросаться в крайности и никогда такого не делать. Можно в какой-то момент дергать mc, если опять же это нужно. Всегда есть выбор. А если разработка завязана на консольке. то значит в этот момент она уже открыта и вероятно в нужном месте (как правило, в корне проекта).

              Просто IDE все стремится засосать в себя. А консоль стремится быть клеем всего и вся.

              Пример: есть virtualenv для питона. И сейчас IDE научились его эмулировать. Хотя сам virtualenv уже года 2 существует, IDE дошли до него только сейчас. И эта поддержка ими не может быть полной по определению. В итоге многие используют virtualenv отдельно а IDE отдельно. А такое дробление (часть делаем в консольке — часть в IDE) тоже не позволяет прочувствовать мощь консоли целиком.
                –1
                16 символов в секунду — это 960 в минуту. Какое здесь «даже при»?

                В Vim очень удобно использовать Command-T для открытия файлов. Впрочем, это не единственное дополнение на эту тему: есть также FuzzyFinder, Unity, ku, LustyExplorer, … А автодополнение файлов в Vim убого. Я как‐то сделал аналог автодополнения файлов в zsh (причём, в zsh автодополнение именно файлов оказалось несколько хуже), но Command-T оказался ещё удобнее, поэтому проект заглох несмотря на несколько очевидных проблем.

                Относительно virtualenv: “workon env” не работает в Vim (в смысле, если запустить workon и затем Vim, встроенная поддержка python будет игнорировать виртуальное окружение, но запущенные из Vim команды игнорировать не будут). Приходится использовать github.com/jmcantrell/vim-virtualenv.
                  0
                  От мании величия я вроде бы уже избавился, как бы не перебрал :)

                  1) Слепой метод мне не даётся, как и, например, переключение передач не глядя на рукоятку или выключение сцепления не глядя на педаль. Вернее не так, не глядя на руки или ногу.

                  2) Я могу печатать ~200 знаков в минуту на клавиатуре где знаки стёрты, но мне нужно видеть свои руки, не глядя на руки 60-80 максимум (если без шифтов), слишком долго представлять движения пальцев и не то что годами, а десятилетиями этот показатель не меняется, хотя бывало две недели только Соло проходил по 12 часов в сутки (5 клавиатур разбил как-то за отпуск).

                  3) Нужно знать путь и название файлов, я их узнаю когда вижу их на экране, а те что помню наизусть (типа /etc/php5/cli/php.ini) редко приходится набирать, как правило только при установке новой системы.

                  Насчёт последнего замечания — я только рад был бы, если бы для моих языков существовали полноценные IDE в TUI. Но, увы, никто их не разрабатывает, а vim/emacs не тянут ввиду, прежде всего, отсутствия синтаксических анализаторов для интеллектуального автодополнения или навигации типа «перейти к определению метода».

                  А насчёт дробления — я же говорил, что консоль мощнее IDE, но мощь эта, имхо, не востребована на типичных задачах, превносит оверхид. Универсальный клей хорошо когда часто приходится клеить разные материалы, а когда одни и те же, то лучше взять узкоспециализированный. Например, можно использовать grep чтобы найти файл, содержащий class UserRepository, и открыть его в vim, но проще кликнуть в строке $repo = new UserRepository(); и нажать Ctrl+B.

                  IDE стремится засосать в себя только то, что нужно для разработки, отсекая, например, то, что нужно для администрирования.

                    0
                    Есть огромная куча дополнений к Vim разной степени работоспособности для различных языков, предоставляющих возможность перехода к определению и интеллектуального автодополнения. Дополнения, использующие синтаксические анализаторы тоже есть, но VimL не даёт (точнее, требует медленных и неприглядных решений) довольно большого количества возможностей их интеграции.

                    Grep обычно делается из Vim, а не из консоли в этом случае, так переход к найденному можно осуществить гораздо быстрее.
                      +1
                      То есть vim превращаем в IDE путем установки дополнений? Вот чем мне ещё нравятся IDE так тем, что скачал и можно работать, не читая мануалов и хелпов (всё равно толком ни разу не помогло их чтение, либо сразу понятно, либо проще из консоли сделать), процентов 90 потребностей будет покрыто «из коробки», ещё 5 путем настройки.
                        0
                        А оставшиеся 5, видимо, не могут быть покрыты в принципе.

                        Мне лично проще жить с более плохим автодополнением, чем настроить IDE под себя: слишком много придётся настраивать, причём значительная часть из этого «много» является либо одной из основных возможностей Vim, либо предоставляется чужими дополнениями с небольшой настройкой. Оставшееся написано самостоятельно.
                          0
                          Сторонние дополнения существуют не только для vim. И потом, есть же ещё консоль :)
                            0
                            Получается, дополнения надо ставить и туда, и туда. Но у меня список дополнений описан в vimrc и для того, чтобы их поставить надо выполнить всего четыре действия:
                            1. Клонировать репозиторий с настройками.
                            2. Создать в нужном месте символические ссылки.
                            3. Клонировать vim-addon-manager.
                            4. Запустить Vim.

                            Vim-addon-manager далее затем сам установит всё, что нужно. Причём первый и третий шаги можно объединить с помощью submodules (я так не сделал, потому что VAM у меня установлен пакетным менеджером) либо поместив в vimrc код, который делает третий шаг (код можно просто скопировать из документации). Конечно, нужен по крайней мере git, но он нужен и с IDE.
                              0
                              Такой способ и в IDE можно применить, я думал что из коробки какой-то репозиторий есть.
                                0
                                Изкоробочное решение не может обладать универсальностью: я не хочу иметь один способ восстановления для IDEVim, другой для zsh, третий для браузера. Вопрос здесь в том, как хранятся эти самые настройки? Не трогал файлы IDE, но с firefox, насколько мне известно, простое копирование файлов в другое место легко может и не пройти. Легко получить различия двух разных версий sqlite базы данных, в которой он и хранит настройки, точно не выйдет (правда, мне это почти никогда не нужно).

                                И ещё — пакетный менеджер там действительно увидев несоответствие между списком дополнений и тем, что реально установлено, начнёт установку недостающих частей? Или придётся заталкивать туда и сами дополнения? VAM, в частности, удобен тем, что если я использую свой vimrc на arm нетбуке, то он загрузит и скомпилирует Command-T. Писать дополнительный код для его компиляции или иметь репозиторий с бинарниками с неправильной архитектурой не требуется.
                                  0
                                  Ну а мне собственно только от IDE настройки и нужны, остальное и не вспомню что настраиваю. По ходу дела разбираюсь: открыл программу, увидел что непривычно себя ведёт — настроил.

                                  Установит вряд ли дополнения, хотя не экспериментировал.
                                    0
                                    У меня основной используемой программой является редактор, но всё же потеря других настроек (zsh, Opera, mplayer, mercurial) была бы весьма неприятной. Особенно zsh и Opera, остальное легко восстановить.

                                    Впрочем, в случае Opera одним репозиторием дело не ограничивается — так как я с самого начала рассматривал возможность сделать его публичным при необходимости, то пароли есть только в резервных копиях.
                                      0
                                      У нас очень разные сценарии использования софта, видимо. bash, vim, sublime, mercurial, браузеры, офис и прочее я практически не настраиваю (если не считать установку расширений к браузеру). Я считаю себя среднестатистическим пользователем этих продуктов, которого должны устраивать настройки из коробки. Только минимальная персонификация в виде ввода мыла, логинов и паролей. Возможно я просто слишком поздно открыл для себя бесплатные хранилища, которым мог бы доверять свою информацию годами, не переживая за то, что она будет утрачена хотя бы из-за того, что я к хранилищу N дней/месяцев/лет не обращался.
                          0
                          Кстати:
                          скачал
                          Зачем вы скачали то, что у вас уже должно стоять довольно давно?
                            0
                            Новый комп, переустановка ОС (вернее обновление через снов и установку новой), работа в новом месте.
                              +1
                              Хорошо, скачали. А куда делся репозиторий с настройками? Или ваши IDE принципиально не позволяют иметь такой?
                                +1
                                Эм… Ни разу не слышал, чтобы у IDE или редактора был репозиторий с настройками. Хотя, наверное, можно написать плагин, который после записи настроек будет коммитить файлы, а потом их пушить куда-нибудь на битбакет, а при запуске пуллить. Только стоит ли овчинка выделки?
                                  0
                                  У редактора или IDE его и так нет. Он есть у меня, и там хранятся все настройки, не только редактора. Кроме того, странно, что вы не слышали: на github 20 449 репозиториев, названных «dotfiles». Значительное количество подобных репозиториев названо по‐другому (у меня — config, но на bitbucket и скрытый).

                                  И это разве сложно? Как раз удобно — хранить настройки в репозитории, чтобы при переустановке ОС/покупке нового компьютера/… не начинать с нуля.

                                  Если также сохранить и /etc (+ аналог /var/lib/portage/world из Gentoo со списком установленных пакетов) (и сделать резервные копии всего из $HOME, что не вошло в репозиторий с настройками), то у вас будет вся информация, необходимая для восстановления системы или отката при неверно выполненной настройке.
                        –1
                        Обладаю:
                        1. Полностью слепым методом печати (за исключением когда моторика сбивается и вместо «привет» печатается «ротает» что является смещением на одну букву на клавиатуре левее)
                        2. В автомобиле всегда смотрю только на дорогу или на любимую девушку справа и никогда на педали (ноги) или ручную коробку передач(руки)

                        Являюсь только начинающим программистом. Раньше занимался системным администрированием.

                        Насчет консоли и IDE:
                        Программирование это не просто набивание символов на клавиатуре что позволяет с легкостью и быстротой выполнять консоль, а еще и поиск по гуглу, стаковерфлоу и другим ресурсам, в некоторых случаях бывает даже копипаст какого-то кода, а потом долгие потуги разобрать его и подогнать под свой проект. А это уже проще делать в ГУИ IDE чем скролить пейдж ап энд даун консольку.
                        Палка о двух концах.
                          +1
                          Вот как раз у Vim одна из самых совершенных систем навигации внутри файла (за исключением штук вроде «перейти к объявлению», не работающих без дополнений). Никаких PageUp/PageDown, работа с Vim вообще не предполагает перемещение рук куда‐либо с основного блока клавиатуры.

                          Кроме того, зачастую нужно сделать «command|xclip -i» и затем нормально вставлять вывод команды куда угодно средней кнопкой мыши. Можно сразу отправить текст на pastebin. Если вывод длиннее одной строчки, а запуск команды два раза быстр и производит одинаковый текст, то в GUI это будет сложнее сделать. Отдельно про SO: у меня есть
                          alias +4='sed "s/^/    /" | xclip -i'

                          , в Vim можно сделать привязку для того же (а можно просто выделить текст и сделать «>gv>», затем вставить). Интересно услышать, как вы копируете код из GUI.

                          Копирование откуда‐то ещё тривиальнее.
                0
                я не очень понял, а как синхронизировать изменения в файловой системе и VCS? Например, я добавил в проект несколько файлов — как не перечисляя поимённо добавить их под контроль VCS? На всякий случай напомню, что IDE это отслеживают.
                  0
                  Находясь в корне проекта: hg/git add ..
                    0
                    а СВН?
                      0
                      То же самое, вроде как.
                    0
                    SCM системы вроде как для таких ситуаций и предназначены, это их прямая обязанность — они сами отслеживают появляющиеся/изменяющиеся файлы. А дальше их можно добавлять либо кучей, либо масками, директориями, либо поимённо. В общем, как хочется.
                      0
                      Некоторые VCS с поименным добавлением справляются лучше :)
                        0
                        Пример можно?
                    +1
                    В целом поддерживаю. Сам разрабатываю в основном в консоли, хотя текст пишу в GUI редакторах. Но grep/find/ls/git всегда под рукой.

                    Насчёт поиска файлов изменённых за последние N дней. Чаще требуется найти все файлы с некоего коммита. Делается это просто:
                    git diff --name-only [commitFrom] [commitTo]

                    Можно указать как commitFrom, например HEAD~5 и получить список файлов изменённых с последних 5 коммитов + если есть не незакомиченные изменения. И если добавить commitTo, то можно ограничить поиск. Например, HEAD. Если нужно сформировать патч и отправить только исправленные файлы в виде архива, можно сделать так:
                    git diff --name-only HEAD~5 HEAD | xargs zip update.zip

                    А если делать подобное подручными графическими средствами? Сколько потребуется телодвижений?

                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                    Самое читаемое