Напишите сценарий оболочки, который будет перемещать все файлы в текущем каталоге, содержащем слово & ldquo; hello & rdquo; в отдельную папку под названием & ldquo; hello-world & rdquo;

У меня есть GTX980 и не удалось войти в систему после обновления до 16.04 (с 15.10). Удалите nvidia:

sudo apt-get purge nvidia*

и вошел в систему. Он работал, но разрешение ограничивалось 800x600.

После устранения этой проблемы моя проблема:

Переустановите nvidia: sudo apt-get install nvidia-361 Перезагрузите, перейдите в BIOS и отключите безопасную загрузку

Спасибо за подсказку, чтобы отключить безопасную загрузку : -

)
1
задан 1 February 2018 в 20:06

6 ответов

Из сценария bash с именем test.sh

#!/bin/sh IFS=$'\n' for i in $( grep -l hello --exclude=*.sh --exclude-dir=hello-world * ); do mv $i hello-world/; done;

Из командной строки:

IFS=$'\n' && for i in $( grep -l hello --exclude-dir=hello-world * ); do mv $i hello-world/; done;

Надеюсь, это поможет вам ...

Please подумайте о создании первого справочного привет-мира.

-1
ответ дан 17 July 2018 в 21:53

Это будет решение, соответствующее вашей идее с помощью grep и xargs:

#!/bin/bash mkdir hello-world grep -l hello * | xargs mv -t hello-world
0
ответ дан 17 July 2018 в 21:53

Давайте разложим это на более мелкие задачи. Нам нужно

создать каталог hello-world, если он не существует, надежно идентифицировать файлы, содержащие текст hello, надежно перемещать файлы в новый каталог.

Создание каталога выполняется с помощью mkdir. Он всегда отказывается создавать каталог, который существует (тем самым отказываясь перезаписывать такие каталоги), но также имеет флаг -p, который, как упоминалось в man mkdir

-p, --parents no error if existing, make parent directories as needed

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

Итак, первая команда нашего скрипта может быть (сначала проверьте, что вы в правильном каталоге).

mkdir -p hello-world

Второй шаг - идентификация файлов, которые мы хотим. Наиболее очевидной командой для поиска текста в файлах является grep. Если нам нужны только имена файлов, которые содержат hello, мы можем использовать флаг -l, который, согласно man grep

-l, --files-with-matches Suppress normal output; instead print the name of each input file from which output would normally have been printed. The scanning will stop on the first match.

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

$ echo hello > with\ space $ ls a b c d e f with space $ for i in $(grep -l hello *); do echo "$i"; done a c f with space

Файл with space рассматривается как два отдельных files.

Чтобы идентифицировать файлы, чтобы оболочка что-то с ними делала, нам следует избегать разбора имен файлов. Мы могли бы протестировать каждый файл, посмотреть, содержит ли он текст, и если это так, переместите его. Чтобы перебрать файлы, как показано выше, мы можем использовать for, который имеет такой синтаксис:

for var in things; do stuff $var; done

Внутри цикла for (и в любом другом месте) мы можем использовать test команда, которая иногда выглядит как [ и также похожа на [[, чтобы сделать условные операторы, и если вы только хотите проверить, был ли файл пустым или нет или был определенного типа, я бы посоветовал вам использовать test.

Но вы хотите найти какой-то конкретный текст, поэтому нам следует называть grep, но мы действительно хотим знать, удалось ли искать hello в файле, поэтому мы знайте, что мы должны что-то делать с файлом.

Чтобы сделать условное утверждение, основанное на успехе команды, мы можем использовать if. if часто используется с test / [ / [[, но вам это не нужно, потому что grep имеет другой полезный флаг:

-q, --quiet, --silent Quiet; do not write anything to standard output. Exit immediately with zero status if any match is found, even if an error was detected.

Zero in Bash означает успех. Чтобы сделать то, что мы хотим, мы могли бы написать что-то вроде

if grep -q hello file; then mv file hello-world; fi

([35] является частью синтаксиса команды if. Он сообщает оболочке, что вы закончили свой if).

Я обычно пишу shell-скрипты в интерактивной оболочке и позже записываю их в файл позже, потому что я ленив, и я в основном пишу очень тривиальные скрипты. В любом случае, вы можете написать короткий скрипт в виде одной строки, разделив команды с помощью ;. Если что-то пойдет не так, нажмите клавишу со стрелкой вверх, чтобы отредактировать последнюю команду ...

Мы не хотим запускать эту команду один раз для каждого файла. Это приведет к поражению объекта написания сценария для выполнения задания и спасению ввода текста, поэтому для обработки файлов мы можем использовать for. Чтобы избежать получения ошибки из grep в каталоге hello-world, мы можем добавить еще один флаг, чтобы исключить его.

Вот моя тестовая команда для выполнения этой работы и вывода, который я получаю от нее в своем тесте environment:

$ mkdir -p hello-world; for file in *; do if grep -q --exclude-dir=hello-world -- hello "$file"; then echo mv -v -- "$file" hello-world; fi; done mv -v -- a hello-world mv -v -- c hello-world mv -v -- f hello-world mv -v -- with space hello-world

Этот скрипт не перемещает файлы из-за echo перед mv, который показывает, какая команда будет выполняться с каждой итерацией цикла. Удалите echo после тестирования, если команды выглядят правильно (обратите внимание, что вы не всегда можете надежно использовать echo для тестирования, и вам, возможно, придется ввести временное цитирование, но оно отлично работает здесь).

* - это все не скрытые файлы в текущем каталоге. Безопаснее использовать ./*, что означает одно и то же, но гарантирует, что все пути начинаются с ./ (который является адресом текущего рабочего каталога .), предотвращая интерпретацию имен файлов, начиная с -, как параметров. Мы рассмотрели эту возможность, добавив -- в grep и в команду mv, чтобы указать конец опций. -v является подробным флагом mv.

Мы должны указывать переменные для подавления разложений оболочки. Если я удалю кавычки вокруг "$file", мой результат будет

mv -v -- a hello-world mv -v -- c hello-world mv -v -- f hello-world grep: with: No such file or directory grep: space: No such file or directory

Вот сценарий как скрипт:

#!/bin/bash mkdir -p hello-world for file in *; do if grep -q --exclude-dir=hello-world -- hello "$file"; then echo mv -v -- "$file" hello-world fi done

Не забудьте удалить echo, когда вы готовы перенести файлы на реальные.

PS, там могут быть более эффективные способы сделать это. Мой путь - всего лишь пример.

3
ответ дан 17 July 2018 в 21:53

Из сценария bash с именем test.sh

#!/bin/sh IFS=$'\n' for i in $( grep -l hello --exclude=*.sh --exclude-dir=hello-world * ); do mv $i hello-world/; done;

Из командной строки:

IFS=$'\n' && for i in $( grep -l hello --exclude-dir=hello-world * ); do mv $i hello-world/; done;

Надеюсь, это поможет вам ...

Please подумайте о создании первого справочного привет-мира.

-1
ответ дан 23 July 2018 в 22:30
  • 1
    Спасибо за ваши отзывы, я отредактировал свой ответ ... – Alvaro Niño 1 February 2018 в 13:01
  • 2
    хорошо, это немного лучше, но он все равно сломается, если имена файлов имеют пробелы (цитирование не исправит) – Zanna 1 February 2018 в 13:02
  • 3
    Большое спасибо @zanna, а теперь? – Alvaro Niño 1 February 2018 в 13:17
  • 4
    Я уже отключил свой downvote, но см. [D0] unix.stackexchange.com/questions/321697/… для общих проблем с подобным подходом – Zanna 1 February 2018 в 13:26
  • 5
    Большое спасибо за вашу помощь, это более важные знания, чем голоса. – Alvaro Niño 1 February 2018 в 13:54

Это будет решение, соответствующее вашей идее с помощью grep и xargs:

#!/bin/bash mkdir hello-world grep -l hello * | xargs mv -t hello-world
0
ответ дан 23 July 2018 в 22:30
  • 1
    Это должно работать для OP, но не удастся, если имена файлов имеют пробелы ... – Zanna 1 February 2018 в 02:03
  • 2
    Параметры -Z и -0 могут помочь в этом. – muru 1 February 2018 в 07:37

Давайте разложим это на более мелкие задачи. Нам нужно

создать каталог hello-world, если он не существует, надежно идентифицировать файлы, содержащие текст hello, надежно перемещать файлы в новый каталог.

Создание каталога выполняется с помощью mkdir. Он всегда отказывается создавать каталог, который существует (тем самым отказываясь перезаписывать такие каталоги), но также имеет флаг -p, который, как упоминалось в man mkdir

-p, --parents no error if existing, make parent directories as needed

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

Итак, первая команда нашего скрипта может быть (сначала проверьте, что вы в правильном каталоге).

mkdir -p hello-world

Второй шаг - идентификация файлов, которые мы хотим. Наиболее очевидной командой для поиска текста в файлах является grep. Если нам нужны только имена файлов, которые содержат hello, мы можем использовать флаг -l, который, согласно man grep

-l, --files-with-matches Suppress normal output; instead print the name of each input file from which output would normally have been printed. The scanning will stop on the first match.

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

$ echo hello > with\ space $ ls a b c d e f with space $ for i in $(grep -l hello *); do echo "$i"; done a c f with space

Файл with space рассматривается как два отдельных files.

Чтобы идентифицировать файлы, чтобы оболочка что-то с ними делала, нам следует избегать разбора имен файлов. Мы могли бы протестировать каждый файл, посмотреть, содержит ли он текст, и если это так, переместите его. Чтобы перебрать файлы, как показано выше, мы можем использовать for, который имеет такой синтаксис:

for var in things; do stuff $var; done

Внутри цикла for (и в любом другом месте) мы можем использовать test команда, которая иногда выглядит как [ и также похожа на [[, чтобы сделать условные операторы, и если вы только хотите проверить, был ли файл пустым или нет или был определенного типа, я бы посоветовал вам использовать test.

Но вы хотите найти какой-то конкретный текст, поэтому нам следует называть grep, но мы действительно хотим знать, удалось ли искать hello в файле, поэтому мы знайте, что мы должны что-то делать с файлом.

Чтобы сделать условное утверждение, основанное на успехе команды, мы можем использовать if. if часто используется с test / [ / [[, но вам это не нужно, потому что grep имеет другой полезный флаг:

-q, --quiet, --silent Quiet; do not write anything to standard output. Exit immediately with zero status if any match is found, even if an error was detected.

Zero in Bash означает успех. Чтобы сделать то, что мы хотим, мы могли бы написать что-то вроде

if grep -q hello file; then mv file hello-world; fi

([35] является частью синтаксиса команды if. Он сообщает оболочке, что вы закончили свой if).

Я обычно пишу shell-скрипты в интерактивной оболочке и позже записываю их в файл позже, потому что я ленив, и я в основном пишу очень тривиальные скрипты. В любом случае, вы можете написать короткий скрипт в виде одной строки, разделив команды с помощью ;. Если что-то пойдет не так, нажмите клавишу со стрелкой вверх, чтобы отредактировать последнюю команду ...

Мы не хотим запускать эту команду один раз для каждого файла. Это приведет к поражению объекта написания сценария для выполнения задания и спасению ввода текста, поэтому для обработки файлов мы можем использовать for. Чтобы избежать получения ошибки из grep в каталоге hello-world, мы можем добавить еще один флаг, чтобы исключить его.

Вот моя тестовая команда для выполнения этой работы и вывода, который я получаю от нее в своем тесте environment:

$ mkdir -p hello-world; for file in *; do if grep -q --exclude-dir=hello-world -- hello "$file"; then echo mv -v -- "$file" hello-world; fi; done mv -v -- a hello-world mv -v -- c hello-world mv -v -- f hello-world mv -v -- with space hello-world

Этот скрипт не перемещает файлы из-за echo перед mv, который показывает, какая команда будет выполняться с каждой итерацией цикла. Удалите echo после тестирования, если команды выглядят правильно (обратите внимание, что вы не всегда можете надежно использовать echo для тестирования, и вам, возможно, придется ввести временное цитирование, но оно отлично работает здесь).

* - это все не скрытые файлы в текущем каталоге. Безопаснее использовать ./*, что означает одно и то же, но гарантирует, что все пути начинаются с ./ (который является адресом текущего рабочего каталога .), предотвращая интерпретацию имен файлов, начиная с -, как параметров. Мы рассмотрели эту возможность, добавив -- в grep и в команду mv, чтобы указать конец опций. -v является подробным флагом mv.

Мы должны указывать переменные для подавления разложений оболочки. Если я удалю кавычки вокруг "$file", мой результат будет

mv -v -- a hello-world mv -v -- c hello-world mv -v -- f hello-world grep: with: No such file or directory grep: space: No such file or directory

Вот сценарий как скрипт:

#!/bin/bash mkdir -p hello-world for file in *; do if grep -q --exclude-dir=hello-world -- hello "$file"; then echo mv -v -- "$file" hello-world fi done

Не забудьте удалить echo, когда вы готовы перенести файлы на реальные.

PS, там могут быть более эффективные способы сделать это. Мой путь - всего лишь пример.

3
ответ дан 23 July 2018 в 22:30
  • 1
    Это совершенно потрясающий ответ на посредственный вопрос! Однако, если бы я был вами (к счастью для вас это не так), я бы не включил сценарий в конец, хотя ученику все равно пришлось бы разбираться в чем-то для себя, но все равно поддерживаться! :-) :-): -) – Fabby 14 February 2018 в 00:08

Другие вопросы по тегам:

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