Почему я не могу редактировать разделы этого USB-накопителя?

Начните с малого

Разбейте проблему на более мелкие части. Одна из причин, по которой вы застряли, заключается в том, что вы пытаетесь создать все решение одним ударом, даже когда вы пытаетесь научиться работать с инструментами, которые используете для создания самого решения.

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

Начните с точного определения того, что необходимо сделать с каждым файлом. На самом деле вы должны быть в состоянии вручную написать команды, необходимые для обработки одного конкретного имени файла, выбранного из вашего списка файлов. Не делайте работу, просто пишите команды. В вашем примере нужно переместить каждый файл, да? Поэтому для каждого файла требуется одна команда mv. Вместо того, чтобы ломать голову над тем, как выполнить команду mv, просто беспокойтесь о том, как ее создать. Как бы вы вручную написали только одну такую ​​mvкоманду для перемещения файла? Тогда возникает вопрос, как получитьawk(или любой другой инструмент, который вы хотите использовать )для вывода этой команды:

mv (filename) (to-where-you-want-it)

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

Для начала посетите страницу manдля поиска инструмента, который, по вашему мнению, вам подойдет. Затем поэкспериментируйте с этой командой в ручном режиме,просто чтобы узнать, что вам нужно сделать, чтобы этот инструмент анализировал ваш ввод так, как вы хотите, и создавал вывод, который вам нужен. Прежде чем вы сможете написать сценарий для перемещения 100 или 1000 файлов, вам нужен сценарий, который может правильно перемещать только один файл. Так что создайте тестовый пример одного и найдите время, которое вам нужно, чтобы «подружиться» с инструментом или инструментами, которые, по вашему мнению, будут работать. Ваш пост помечен , и я думаю, что это мудрый выбор, так что давайте так.

awkимеет параметр -F, который можно использовать для указания разделителя, который awkдолжен использовать для разбиения строки на составные поля. Этот разделитель может быть простым символом или любым из нескольких символов, заключенных в квадратные скобки. На языке регулярных выражений это известно как класс символов . Ваш ввод использует как дефис '-', так и точку '.'в качестве разделителей полей, поэтому мы можем указать класс символов [-.], чтобы сообщить awkо разделении либо на дефис, либо на точку. Внимательно заметьте, что awkне важно, какой из них какой, и убедитесь, что ваши исходные каталоги не содержат никаких дефисов или точек.

Использование awkдля разбиения каждого имени файла на составные поля

Возьмите пример с именем файла A1-001.xyzи попробуйте запустить его с помощью этой команды awkвручную, чтобы узнать, что awkделает с этим именем файла:

$ awk -F[-.] '{print $0 " " $1 " " $2 " " $3}' <<< 'A1-001.xyz'

Эта команда сообщает awk, «Используя дефис и точку в качестве разделителей полей, напечатайте всю строку ввода ($0), пробел, поле 1, пробел, поле 2, пробел и, наконец, поле 3.

Вывод:

A1-001.xyz A1 001 xyz

Надеюсь, это показало вам многое, :что $0— это то, что вам нужно в исходном коде команды mv, потому что это полное исходное имя файла; и это $2— это то, что вам нужно в назначении команды mv, потому что это числовое имя каталога, которое вам нужно. Самое большое осознание заключается в том, что awkможет полностью отформатировать команду mvдля вас и распечатать ее.Все, что для этого требуется, — это немного изменить оператор awkprint. Вместо того, чтобы пытаться заставить ваш скрипт делать все, просто пусть скрипт создаст команды, которые вам нужно выполнить. Таким образом, ошибка в ваших сценариях не приведет к его взрыву и перемещению файлов в неправильные места. Он просто напечатает какой-то неправильный вывод, и вы заметите, что это неправильно, но вреда не будет.

Вторая итерация уточнения команды awk

Перед именем файла может быть исходный путь. Но убедитесь, что в пути нет символов .или -! Таким образом, команда mvдля каждого файла, очевидно, начинается с mvи пробела, затем имя файла (, включая полный исходный путь, возможно, ), еще один пробел и каталог, в который вы перемещаете файл. На всякий случай мы поместим косую черту после каталога назначения. Поскольку вы не меняете имя файла, мы просто укажем каталог назначения и опустим имя файла назначения. Делать это также проще, что стоит отметить. Не усложняйте задачу больше, чем это необходимо.

$ awk -F[-.] '{print "mv " $0 " " $2 "/"}' <<< '/path/to/directory1/A1-001.xyz'
mv /path/to/directory1/A1-001.xyz 001/

Посмотрите на команду print, :начинается с mvпробела, затем $0— полное имя файла; другой пробел, затем $2, который является выходным подкаталогом -. Опять же, вы должны убедиться, что ваши исходные пути НЕ содержат каких-либо дефисов или точек, потому что они имеют особое значение как разделители полей в ваших именах файлов. Проблема еще в том, что awkне разделит ваши поля должным образом, и ваш скрипт сломается.

Но целевой каталог — это не просто $2, перед ним стоит префикс, как и перед именем исходного файла. Мы можем заставить awkраспечатать это для нас, так как это каждый раз одно и то же :

.

$ awk -F[-.] '{print "mv " $0 " /path/to/directory2/" $2 "/"}' <<< '/path/to/directory1/A1-001.xyz'
mv /path/to/directory1/A1-001.xyz /path/to/directory2/001/

Протестируйте решение по всему списку файлов

Выглядит многообещающе.Теперь составьте список файлов вfile-list.txt:

$ cat file-list.txt 
A1-001.xyz
A29-002.xyz
A82-003.xyz

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

$ awk -F[-.] '{print "mv " $0 " /path/to/directory2/" $2 "/"}' < file-list.txt 
mv A1-001.xyz /path/to/directory2/001/
mv A29-002.xyz /path/to/directory2/002/
mv A82-003.xyz /path/to/directory2/003/

Внимательно проверьте выходные данные, протестируйте и выполните

Если вам нужно переместить большое количество файлов, вы можете передать приведенную выше команду awkв less, чтобы вы могли внимательно ее изучить. Ищите точки и тире в неправильных местах или другие странные символы в именах файлов или каталогов. Если вы хотите, вы можете скопировать -и -и вставить образец строки этого вывода в приглашение оболочки, чтобы убедиться, что он работает правильно. Но это достаточно простой пример, который мы можем проверить путем проверки. Как только вы убедитесь, что этот список команд mv— это то, что вы хотите сделать, просто направьте вывод awkпрямо в shдля его выполнения. Если вы хотите видеть команды во время их выполнения, используйте sh -vвместо простоsh:

$ awk -F[-.] '{print "mv " $0 " /path/to/directory2/" $2 "/"}' < file-list.txt | sh -v
mv A1-001.xyz /path/to/directory2/001/
mv A29-002.xyz /path/to/directory2/002/
mv A82-003.xyz /path/to/directory2/003/
$

Заключение

Надеюсь, вы не возражаете против такой подробной разбивки, но такого рода вопросы часто возникают на Stack Exchange, и многие начинающие скриптеры считают, что их проблема — уникальная, -нестандартная проблема, которая требует уникальное решение.

Настоящим ключом к написанию сценариев является осознание того, что сценарии предоставляют универсальные инструменты, которые могут решать самые разные задачи, и одним из первых шагов к получению навыков является изучение того, как делать небольшие вещи с помощью этих инструментов, а затем комбинировать их. маленькие вещи в большие и большие вещи.

Первый шаг состоял в том, чтобы просто научиться говорить awkкак разбить имя файла так, как нам нужно. Это критический шаг каждый раз, когда вы пытаетесь проанализировать поля компонентов из имени файла, в который встроено несколько фрагментов информации.

Вторым шагом было указание awk автоматически печатать части команды, которые всегда были одинаковыми для каждого файла (mv в начале, путь назначения перед полем $2), и разместить извлеченные поля имени файла в правильных местах. Операторы printи им подобные являются одной из самых основных частей любого типа кодирования, и я не могу припомнить большого вреда, который когда-либо причинялся оператором well -place print. Чтобы быть уверенным, вы хотите выводить только то, что необходимо, но когда вы учитесь и не знаете, что такое переменная, напечатайте ее, спросить редко бывает больно. В долгосрочной перспективе вы вернете этот оператор печати обратно, но весь смысл техники написания сценариев «напечатать -это -, затем -передать -в -оболочку» заключается в том, что у вас есть " пробный прогон», потому что вы всегда просматриваете команды оболочки, выводимые вашим сценарием, прежде чем вы на самом деле передаете их оболочке для выполнения. В сложных случаях даже добавление комментариев в ваш вывод является честной игрой, чтобы «показать вашу работу» :

.

$ awk -F[-.] '{print "# move file " $0 " to subdir " $2; print "mv " $0 " /path/to/directory2/" $2 "/"}' < file-list.txt 
# move file A1-001.xyz to subdir 001
mv A1-001.xyz /path/to/directory2/001/
# move file A29-002.xyz to subdir 002
mv A29-002.xyz /path/to/directory2/002/
# move file A82-003.xyz to subdir 003
mv A82-003.xyz /path/to/directory2/003/

И третий ключ, возможно, тесно связанный с моим вторым пунктом, но который, как мне кажется, часто упускается из виду: когда вы делаете что-то, что требует от вас некоторого напряжения, не пишите сценарий, который потенциально может пойти ошибаетесь и оставляете свои файлы разбросанными по множеству разных, но неправильных мест. Просто напишите скрипт, который пишет скрипт для выполнения работы. Так гораздо проще устранять неполадки. Затем, когда у вас, наконец, будет правильный сценарий, просто передайте вывод сценария (в вашем примере, серию команд mv, по одной на файл )в оболочку, и они будут запущены.

3
30.08.2021, 09:04
0 ответов

Теги

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