Ubuntu 16.04 использует среду рабочего стола Unity, тогда как в 18.04 в настоящее время используется Gnome 3.28.1. Чтобы установить Unity на Ubuntu 18.04, откройте терминал и введите sudo apt update && sudo apt install ubuntu-unity-desktop. Вам будет предоставлен выбор между менеджерами дисплеев. LightDM - это диспетчер отображения по умолчанию для рабочего стола Unity, но любой из них должен работать.
Взгляните на эту ссылку, чтобы получить подробное объяснение. Также посмотрите на NoobsLab. Если вы хотите, чтобы значки док-станции менялись без установки всей рабочей среды. Различные расширения Gnome Shell, такие как Dash to Dock, также позволяют выполнять множество настроек.
У Bash есть специальная переменная IFS.
используется bash, чтобы знать, как разбить строку на список файлов. (Внутренний разделитель полей)
По умолчанию он содержит пробел, табуляцию и новую строку.
for f in `find ... будет разделяться на символы, содержащиеся в переменной $ IFS. Если в именах файлов, возвращаемых командой find, есть новая строка или пробел, она будет рассматриваться как другое имя файла, и, таким образом, цикл будет выполняться для каждой части имени.
$ ls -l -rw-r--r-- 1 marko marko 0 2010-11-01 12:06 my?bad.exe -rw-r--r-- 1 marko marko 0 2010-11-01 12:06 space bad.exe $ for f in $(find -name "*.exe"); do echo "ITERATING ($f)"; done ITERATING (./space) ITERATING (bad.exe) ITERATING (./my) ITERATING (bad.exe)We может настроить переменную $ IFS, но это сложно. Давайте посмотрим, почему:
(Проверьте этот код в сценариях, чтобы изменение переменной IFS не осталось в вашей оболочке, вы можете запутаться)
$ IFS=""; for f in $(find -name "*.exe"); do echo "ITERATING ($f)"; done ITERATING (./space bad.exe ./my bad.exe)Как вы можно увидеть, теперь у bash нет правила разбивать строку, возвращаемую командой find, и обрабатывает весь вывод как одно значение.
Ясно, что проблема заключается в том, что если мы используем for f in `find...., мы не можем отличить новую строку, содержащуюся в файле, от новой строки, сгенерированной командой find.
Теперь ради полноты я покажу вам, как сделать ваш подход работать, но, пожалуйста, см. более легкое решение в конце ответа.
Мы могли бы использовать другие символы разделителя и исправить вашу текущую проблему:
[ f3]Здесь команда find -name "*.exe" -exec echo -n {}: \; возвращает список файлов, разделенных символом «:» (которые не являются законными в именах файлов Windows).
Теперь следующим шагом было бы фактически удалить эти файлы. Учитывайте, что последний файл заканчивается символом «:», и, таким образом, bash выполняет итерацию в последний раз с пустой строкой.
IFS=":"; for f in $(find -name "*.exe" -exec echo -n {}: \;); do if [ ! -z "$f" ]; then rm "$f"; fi; done;Вы должны также выполнить свой тест basename / dirname в этом цикле , как вы это делали раньше.
Однако это решение является уродливым и работает только потому, что мы имеем символ, на который мы можем положиться.
Получается что команда find сама может выполнять команды для каждого найденного файла.
find -name "*.exe" -exec ./yourscript.sh {} \;Затем yourscript.sh wil lget полное имя в $ 1, и вы можете удалить его с помощью rm "$1", даже если он содержит новые строки и пробелы .
Команда find также может использоваться для выполнения встроенного теста basename / dirname внутри вашего скрипта, но это более продвинутая тема.
У Bash есть специальная переменная IFS.
используется bash, чтобы знать, как разбить строку на список файлов. (Внутренний разделитель полей)
По умолчанию он содержит пробел, табуляцию и новую строку.
for f in `find ... будет разделяться на символы, содержащиеся в переменной $ IFS. Если в именах файлов, возвращаемых командой find, есть новая строка или пробел, она будет рассматриваться как другое имя файла, и, таким образом, цикл будет выполняться для каждой части имени.
$ ls -l -rw-r--r-- 1 marko marko 0 2010-11-01 12:06 my?bad.exe -rw-r--r-- 1 marko marko 0 2010-11-01 12:06 space bad.exe $ for f in $(find -name "*.exe"); do echo "ITERATING ($f)"; done ITERATING (./space) ITERATING (bad.exe) ITERATING (./my) ITERATING (bad.exe)We может настроить переменную $ IFS, но это сложно. Давайте посмотрим, почему:
(Проверьте этот код в сценариях, чтобы изменение переменной IFS не осталось в вашей оболочке, вы можете запутаться)
$ IFS=""; for f in $(find -name "*.exe"); do echo "ITERATING ($f)"; done ITERATING (./space bad.exe ./my bad.exe)Как вы можно увидеть, теперь у bash нет правила разбивать строку, возвращаемую командой find, и обрабатывает весь вывод как одно значение.
Ясно, что проблема заключается в том, что если мы используем for f in `find...., мы не можем отличить новую строку, содержащуюся в файле, от новой строки, сгенерированной командой find.
Теперь ради полноты я покажу вам, как сделать ваш подход работать, но, пожалуйста, см. более легкое решение в конце ответа.
Мы могли бы использовать другие символы разделителя и исправить вашу текущую проблему:
$ for f in $(find -name "*.exe" -exec echo -n {}: \;); do echo "ITERATING ($f)"; done; ITERATING (./space bad.exe) ITERATING (./my bad.exe) ITERATING ()Здесь команда find -name "*.exe" -exec echo -n {}: \; возвращает список файлов, разделенных символом «:» (которые не являются законными в именах файлов Windows).
Теперь следующим шагом было бы фактически удалить эти файлы. Учитывайте, что последний файл заканчивается символом «:», и, таким образом, bash выполняет итерацию в последний раз с пустой строкой.
IFS=":"; for f in $(find -name "*.exe" -exec echo -n {}: \;); do if [ ! -z "$f" ]; then rm "$f"; fi; done;Вы должны также выполнить свой тест basename / dirname в этом цикле , как вы это делали раньше.
Однако это решение является уродливым и работает только потому, что мы имеем символ, на который мы можем положиться.
Получается что команда find сама может выполнять команды для каждого найденного файла.
find -name "*.exe" -exec ./yourscript.sh {} \;Затем yourscript.sh wil lget полное имя в $ 1, и вы можете удалить его с помощью rm "$1", даже если он содержит новые строки и пробелы .
Команда find также может использоваться для выполнения встроенного теста basename / dirname внутри вашего скрипта, но это более продвинутая тема.
У Bash есть специальная переменная IFS.
используется bash, чтобы знать, как разбить строку на список файлов. (Внутренний разделитель полей)
По умолчанию он содержит пробел, табуляцию и новую строку.
for f in `find ... будет разделяться на символы, содержащиеся в переменной $ IFS. Если в именах файлов, возвращаемых командой find, есть новая строка или пробел, она будет рассматриваться как другое имя файла, и, таким образом, цикл будет выполняться для каждой части имени.
$ ls -l -rw-r--r-- 1 marko marko 0 2010-11-01 12:06 my?bad.exe -rw-r--r-- 1 marko marko 0 2010-11-01 12:06 space bad.exe $ for f in $(find -name "*.exe"); do echo "ITERATING ($f)"; done ITERATING (./space) ITERATING (bad.exe) ITERATING (./my) ITERATING (bad.exe)We может настроить переменную $ IFS, но это сложно. Давайте посмотрим, почему:
(Проверьте этот код в сценариях, чтобы изменение переменной IFS не осталось в вашей оболочке, вы можете запутаться)
$ IFS=""; for f in $(find -name "*.exe"); do echo "ITERATING ($f)"; done ITERATING (./space bad.exe ./my bad.exe)Как вы можно увидеть, теперь у bash нет правила разбивать строку, возвращаемую командой find, и обрабатывает весь вывод как одно значение.
Ясно, что проблема заключается в том, что если мы используем for f in `find...., мы не можем отличить новую строку, содержащуюся в файле, от новой строки, сгенерированной командой find.
Теперь ради полноты я покажу вам, как сделать ваш подход работать, но, пожалуйста, см. более легкое решение в конце ответа.
Мы могли бы использовать другие символы разделителя и исправить вашу текущую проблему:
$ for f in $(find -name "*.exe" -exec echo -n {}: \;); do echo "ITERATING ($f)"; done; ITERATING (./space bad.exe) ITERATING (./my bad.exe) ITERATING ()Здесь команда find -name "*.exe" -exec echo -n {}: \; возвращает список файлов, разделенных символом «:» (которые не являются законными в именах файлов Windows).
Теперь следующим шагом было бы фактически удалить эти файлы. Учитывайте, что последний файл заканчивается символом «:», и, таким образом, bash выполняет итерацию в последний раз с пустой строкой.
IFS=":"; for f in $(find -name "*.exe" -exec echo -n {}: \;); do if [ ! -z "$f" ]; then rm "$f"; fi; done;Вы должны также выполнить свой тест basename / dirname в этом цикле , как вы это делали раньше.
Однако это решение является уродливым и работает только потому, что мы имеем символ, на который мы можем положиться.
Получается что команда find сама может выполнять команды для каждого найденного файла.
find -name "*.exe" -exec ./yourscript.sh {} \;Затем yourscript.sh wil lget полное имя в $ 1, и вы можете удалить его с помощью rm "$1", даже если он содержит новые строки и пробелы .
Команда find также может использоваться для выполнения встроенного теста basename / dirname внутри вашего скрипта, но это более продвинутая тема.
У Bash есть специальная переменная IFS.
используется bash, чтобы знать, как разбить строку на список файлов. (Внутренний разделитель полей)
По умолчанию он содержит пробел, табуляцию и новую строку.
for f in `find ... будет разделяться на символы, содержащиеся в переменной $ IFS. Если в именах файлов, возвращаемых командой find, есть новая строка или пробел, она будет рассматриваться как другое имя файла, и, таким образом, цикл будет выполняться для каждой части имени.
$ ls -l -rw-r--r-- 1 marko marko 0 2010-11-01 12:06 my?bad.exe -rw-r--r-- 1 marko marko 0 2010-11-01 12:06 space bad.exe $ for f in $(find -name "*.exe"); do echo "ITERATING ($f)"; done ITERATING (./space) ITERATING (bad.exe) ITERATING (./my) ITERATING (bad.exe)We может настроить переменную $ IFS, но это сложно. Давайте посмотрим, почему:
(Проверьте этот код в сценариях, чтобы изменение переменной IFS не осталось в вашей оболочке, вы можете запутаться)
$ IFS=""; for f in $(find -name "*.exe"); do echo "ITERATING ($f)"; done ITERATING (./space bad.exe ./my bad.exe)Как вы можно увидеть, теперь у bash нет правила разбивать строку, возвращаемую командой find, и обрабатывает весь вывод как одно значение.
Ясно, что проблема заключается в том, что если мы используем for f in `find...., мы не можем отличить новую строку, содержащуюся в файле, от новой строки, сгенерированной командой find.
Теперь ради полноты я покажу вам, как сделать ваш подход работать, но, пожалуйста, см. более легкое решение в конце ответа.
Мы могли бы использовать другие символы разделителя и исправить вашу текущую проблему:
$ for f in $(find -name "*.exe" -exec echo -n {}: \;); do echo "ITERATING ($f)"; done; ITERATING (./space bad.exe) ITERATING (./my bad.exe) ITERATING ()Здесь команда find -name "*.exe" -exec echo -n {}: \; возвращает список файлов, разделенных символом «:» (которые не являются законными в именах файлов Windows).
Теперь следующим шагом было бы фактически удалить эти файлы. Учитывайте, что последний файл заканчивается символом «:», и, таким образом, bash выполняет итерацию в последний раз с пустой строкой.
IFS=":"; for f in $(find -name "*.exe" -exec echo -n {}: \;); do if [ ! -z "$f" ]; then rm "$f"; fi; done;Вы должны также выполнить свой тест basename / dirname в этом цикле , как вы это делали раньше.
Однако это решение является уродливым и работает только потому, что мы имеем символ, на который мы можем положиться.
Получается что команда find сама может выполнять команды для каждого найденного файла.
find -name "*.exe" -exec ./yourscript.sh {} \;Затем yourscript.sh wil lget полное имя в $ 1, и вы можете удалить его с помощью rm "$1", даже если он содержит новые строки и пробелы .
Команда find также может использоваться для выполнения встроенного теста basename / dirname внутри вашего скрипта, но это более продвинутая тема.
У Bash есть специальная переменная IFS.
используется bash, чтобы знать, как разбить строку на список файлов. (Внутренний разделитель полей)
По умолчанию он содержит пробел, табуляцию и новую строку.
for f in `find ... будет разделяться на символы, содержащиеся в переменной $ IFS. Если в именах файлов, возвращаемых командой find, есть новая строка или пробел, она будет рассматриваться как другое имя файла, и, таким образом, цикл будет выполняться для каждой части имени.
$ ls -l -rw-r--r-- 1 marko marko 0 2010-11-01 12:06 my?bad.exe -rw-r--r-- 1 marko marko 0 2010-11-01 12:06 space bad.exe $ for f in $(find -name "*.exe"); do echo "ITERATING ($f)"; done ITERATING (./space) ITERATING (bad.exe) ITERATING (./my) ITERATING (bad.exe)We может настроить переменную $ IFS, но это сложно. Давайте посмотрим, почему:
(Проверьте этот код в сценариях, чтобы изменение переменной IFS не осталось в вашей оболочке, вы можете запутаться)
$ IFS=""; for f in $(find -name "*.exe"); do echo "ITERATING ($f)"; done ITERATING (./space bad.exe ./my bad.exe)Как вы можно увидеть, теперь у bash нет правила разбивать строку, возвращаемую командой find, и обрабатывает весь вывод как одно значение.
Ясно, что проблема заключается в том, что если мы используем for f in `find...., мы не можем отличить новую строку, содержащуюся в файле, от новой строки, сгенерированной командой find.
Теперь ради полноты я покажу вам, как сделать ваш подход работать, но, пожалуйста, см. более легкое решение в конце ответа.
Мы могли бы использовать другие символы разделителя и исправить вашу текущую проблему:
$ for f in $(find -name "*.exe" -exec echo -n {}: \;); do echo "ITERATING ($f)"; done; ITERATING (./space bad.exe) ITERATING (./my bad.exe) ITERATING ()Здесь команда find -name "*.exe" -exec echo -n {}: \; возвращает список файлов, разделенных символом «:» (которые не являются законными в именах файлов Windows).
Теперь следующим шагом было бы фактически удалить эти файлы. Учитывайте, что последний файл заканчивается символом «:», и, таким образом, bash выполняет итерацию в последний раз с пустой строкой.
IFS=":"; for f in $(find -name "*.exe" -exec echo -n {}: \;); do if [ ! -z "$f" ]; then rm "$f"; fi; done;Вы должны также выполнить свой тест basename / dirname в этом цикле , как вы это делали раньше.
Однако это решение является уродливым и работает только потому, что мы имеем символ, на который мы можем положиться.
Получается что команда find сама может выполнять команды для каждого найденного файла.
find -name "*.exe" -exec ./yourscript.sh {} \;Затем yourscript.sh wil lget полное имя в $ 1, и вы можете удалить его с помощью rm "$1", даже если он содержит новые строки и пробелы .
Команда find также может использоваться для выполнения встроенного теста basename / dirname внутри вашего скрипта, но это более продвинутая тема.
У Bash есть специальная переменная IFS.
используется bash, чтобы знать, как разбить строку на список файлов. (Внутренний разделитель полей)
По умолчанию он содержит пробел, табуляцию и новую строку.
для f в `find ...
будет разделяться на символы, содержащиеся в переменной $ IFS. Если в именах файлов, возвращаемых командой find, есть новая строка или пробел, она будет рассматриваться как другое имя файла, и, таким образом, цикл будет выполняться для каждой части имени.
$ ls -l -rw-r - r-- 1 marko marko 0 2010-11-01 12:06 my? bad.exe -rw-r - r-- 1 marko marko 0 2010-11-01 12:06 пространство плохое. exe $ для f в $ (find -name "* .exe"); do echo "ITERATING ($ f)"; done (./space) ITERATING (bad.exe) ITERATING (./my) ITERATING (bad.exe)
Мы могли бы настроить переменную $ IFS, но это сложно. Давайте посмотрим, почему:
(Проверьте этот код в сценариях, чтобы изменение переменной IFS не осталось в вашей оболочке, вы можете запутаться)
$ IFS = "" ; для f в $ (find -name "* .exe"); do echo "ITERATING ($ f)"; done (./space bad.exe ./my bad.exe)
Как вы можете видеть, теперь у bash нет никакого правила разбивать строку, возвращаемую командой find, и обрабатывает целое выводить как одно значение.
Ясно, что проблема заключается в том, что если мы используем для f в `find ....
, мы не можем отличить новую строку, содержащуюся в файле, от новой строки, сгенерированной find!
Теперь для полноты я покажу вам, как заставить ваш подход работать, но, пожалуйста, см. более легкое решение в конце ответа.
Мы могли бы использовать другие разделители и исправить вашу текущую проблему:
$ для f в $ (find -name "* .exe" -exec echo -n {}: \;); do echo "ITERATING ($ f)"; сделанный; ITERATING (./space bad.exe) ITERATING (./my bad.exe) ITERATING ()
Здесь find -name "* .exe" -exec echo -n {}: \ ; команда
возвращает список файлов, разделенных символом «:» (которые не являются законными в именах файлов Windows).
Теперь следующим шагом было бы фактически удалить эти файлы. Учитывайте, что последний файл заканчивается символом «:», и поэтому bash выполняет итерацию в последний раз с пустой строкой.
IFS = ":"; для f в $ (find -name "* .exe" -exec echo -n {}: \;); сделайте, если [! -z "$ f"]; то rm "$ f"; Fi; сделанный;
Вы должны быть в состоянии выполнить также свой тест basename / dirname в этом цикле, как и раньше.
Однако это решение является уродливым и работает только потому, что мы имеем символ, на который мы можем положиться.
Оказывается, что команда find сама может выполнять команды для каждого найденного файла.
find -name "* .exe" -exec. /yourscript.sh {} \;
Затем yourscript.sh wil lget полное имя в $ 1, и вы можете удалить с помощью rm "$ 1"
, даже если он содержит символы новой строки и пробелы.
find команда также может использоваться для выполнения встроенного теста basename / dirname внутри вашего скрипта, но это более продвинутая тема.
У Bash есть специальная переменная IFS.
используется bash, чтобы знать, как разбить строку на список файлов. (Внутренний разделитель полей)
По умолчанию он содержит пробел, табуляцию и новую строку.
для f в `find ...
будет разделяться на символы, содержащиеся в переменной $ IFS. Если в именах файлов, возвращаемых командой find, есть новая строка или пробел, она будет рассматриваться как другое имя файла, и, таким образом, цикл будет выполняться для каждой части имени.
$ ls -l -rw-r - r-- 1 marko marko 0 2010-11-01 12:06 my? bad.exe -rw-r - r-- 1 marko marko 0 2010-11-01 12:06 пространство плохое. exe $ для f в $ (find -name "* .exe"); do echo "ITERATING ($ f)"; done (./space) ITERATING (bad.exe) ITERATING (./my) ITERATING (bad.exe)
Мы могли бы настроить переменную $ IFS, но это сложно. Давайте посмотрим, почему:
(Проверьте этот код в сценариях, чтобы изменение переменной IFS не осталось в вашей оболочке, вы можете запутаться)
$ IFS = "" ; для f в $ (find -name "* .exe"); do echo "ITERATING ($ f)"; done (./space bad.exe ./my bad.exe)
Как вы можете видеть, теперь у bash нет никакого правила разбивать строку, возвращаемую командой find, и обрабатывает целое выводить как одно значение.
Ясно, что проблема заключается в том, что если мы используем для f в `find ....
, мы не можем отличить новую строку, содержащуюся в файле, от новой строки, сгенерированной find!
Теперь для полноты я покажу вам, как заставить ваш подход работать, но, пожалуйста, см. более легкое решение в конце ответа.
Мы могли бы использовать другие разделители и исправить вашу текущую проблему:
$ для f в $ (find -name "* .exe" -exec echo -n {}: \;); do echo "ITERATING ($ f)"; сделанный; ITERATING (./space bad.exe) ITERATING (./my bad.exe) ITERATING ()
Здесь find -name "* .exe" -exec echo -n {}: \ ; команда
возвращает список файлов, разделенных символом «:» (которые не являются законными в именах файлов Windows).
Теперь следующим шагом было бы фактически удалить эти файлы. Учитывайте, что последний файл заканчивается символом «:», и поэтому bash выполняет итерацию в последний раз с пустой строкой.
IFS = ":"; для f в $ (find -name "* .exe" -exec echo -n {}: \;); сделайте, если [! -z "$ f"]; то rm "$ f"; Fi; сделанный;
Вы должны быть в состоянии выполнить также свой тест basename / dirname в этом цикле, как и раньше.
Однако это решение является уродливым и работает только потому, что мы имеем символ, на который мы можем положиться.
Оказывается, что команда find сама может выполнять команды для каждого найденного файла.
find -name "* .exe" -exec. /yourscript.sh {} \;
Затем yourscript.sh wil lget полное имя в $ 1, и вы можете удалить с помощью rm "$ 1"
, даже если он содержит символы новой строки и пробелы.
find команда также может использоваться для выполнения встроенного теста basename / dirname внутри вашего скрипта, но это более продвинутая тема.
У Bash есть специальная переменная IFS.
используется bash, чтобы знать, как разбить строку на список файлов. (Внутренний разделитель полей)
По умолчанию он содержит пробел, табуляцию и новую строку.
для f в `find ...
будет разделяться на символы, содержащиеся в переменной $ IFS. Если в именах файлов, возвращаемых командой find, есть новая строка или пробел, она будет рассматриваться как другое имя файла, и, таким образом, цикл будет выполняться для каждой части имени.
$ ls -l -rw-r - r-- 1 marko marko 0 2010-11-01 12:06 my? bad.exe -rw-r - r-- 1 marko marko 0 2010-11-01 12:06 пространство плохое. exe $ для f в $ (find -name "* .exe"); do echo "ITERATING ($ f)"; done (./space) ITERATING (bad.exe) ITERATING (./my) ITERATING (bad.exe)
Мы могли бы настроить переменную $ IFS, но это сложно. Давайте посмотрим, почему:
(Проверьте этот код в сценариях, чтобы изменение переменной IFS не осталось в вашей оболочке, вы можете запутаться)
$ IFS = "" ; для f в $ (find -name "* .exe"); do echo "ITERATING ($ f)"; done (./space bad.exe ./my bad.exe)
Как вы можете видеть, теперь у bash нет никакого правила разбивать строку, возвращаемую командой find, и обрабатывает целое выводить как одно значение.
Ясно, что проблема заключается в том, что если мы используем для f в `find ....
, мы не можем отличить новую строку, содержащуюся в файле, от новой строки, сгенерированной find!
Теперь для полноты я покажу вам, как заставить ваш подход работать, но, пожалуйста, см. более легкое решение в конце ответа.
Мы могли бы использовать другие разделители и исправить вашу текущую проблему:
$ для f в $ (find -name "* .exe" -exec echo -n {}: \;); do echo "ITERATING ($ f)"; сделанный; ITERATING (./space bad.exe) ITERATING (./my bad.exe) ITERATING ()
Здесь find -name "* .exe" -exec echo -n {}: \ ; команда
возвращает список файлов, разделенных символом «:» (которые не являются законными в именах файлов Windows).
Теперь следующим шагом было бы фактически удалить эти файлы. Учитывайте, что последний файл заканчивается символом «:», и поэтому bash выполняет итерацию в последний раз с пустой строкой.
IFS = ":"; для f в $ (find -name "* .exe" -exec echo -n {}: \;); сделайте, если [! -z "$ f"]; то rm "$ f"; Fi; сделанный;
Вы должны быть в состоянии выполнить также свой тест basename / dirname в этом цикле, как и раньше.
Однако это решение является уродливым и работает только потому, что мы имеем символ, на который мы можем положиться.
Оказывается, что команда find сама может выполнять команды для каждого найденного файла.
find -name "* .exe" -exec. /yourscript.sh {} \;
Затем yourscript.sh wil lget полное имя в $ 1, и вы можете удалить с помощью rm "$ 1"
, даже если он содержит символы новой строки и пробелы.
find команда также может использоваться для выполнения встроенного теста basename / dirname внутри вашего скрипта, но это более продвинутая тема.
У Bash есть специальная переменная IFS.
используется bash, чтобы знать, как разбить строку на список файлов. (Внутренний разделитель полей)
По умолчанию он содержит пробел, табуляцию и новую строку.
для f в `find ...
будет разделяться на символы, содержащиеся в переменной $ IFS. Если в именах файлов, возвращаемых командой find, есть новая строка или пробел, она будет рассматриваться как другое имя файла, и, таким образом, цикл будет выполняться для каждой части имени.
$ ls -l -rw-r - r-- 1 marko marko 0 2010-11-01 12:06 my? bad.exe -rw-r - r-- 1 marko marko 0 2010-11-01 12:06 пространство плохое. exe $ для f в $ (find -name "* .exe"); do echo "ITERATING ($ f)"; done (./space) ITERATING (bad.exe) ITERATING (./my) ITERATING (bad.exe)
Мы могли бы настроить переменную $ IFS, но это сложно. Давайте посмотрим, почему:
(Проверьте этот код в сценариях, чтобы изменение переменной IFS не осталось в вашей оболочке, вы можете запутаться)
$ IFS = "" ; для f в $ (find -name "* .exe"); do echo "ITERATING ($ f)"; done (./space bad.exe ./my bad.exe)
Как вы можете видеть, теперь у bash нет никакого правила разбивать строку, возвращаемую командой find, и обрабатывает целое выводить как одно значение.
Ясно, что проблема заключается в том, что если мы используем для f в `find ....
, мы не можем отличить новую строку, содержащуюся в файле, от новой строки, сгенерированной find!
Теперь для полноты я покажу вам, как заставить ваш подход работать, но, пожалуйста, см. более легкое решение в конце ответа.
Мы могли бы использовать другие разделители и исправить вашу текущую проблему:
$ для f в $ (find -name "* .exe" -exec echo -n {}: \;); do echo "ITERATING ($ f)"; сделанный; ITERATING (./space bad.exe) ITERATING (./my bad.exe) ITERATING ()
Здесь find -name "* .exe" -exec echo -n {}: \ ; команда
возвращает список файлов, разделенных символом «:» (которые не являются законными в именах файлов Windows).
Теперь следующим шагом было бы фактически удалить эти файлы. Учитывайте, что последний файл заканчивается символом «:», и поэтому bash выполняет итерацию в последний раз с пустой строкой.
IFS = ":"; для f в $ (find -name "* .exe" -exec echo -n {}: \;); сделайте, если [! -z "$ f"]; то rm "$ f"; Fi; сделанный;
Вы должны быть в состоянии выполнить также свой тест basename / dirname в этом цикле, как и раньше.
Однако это решение является уродливым и работает только потому, что мы имеем символ, на который мы можем положиться.
Оказывается, что команда find сама может выполнять команды для каждого найденного файла.
find -name "* .exe" -exec. /yourscript.sh {} \;
Затем yourscript.sh wil lget полное имя в $ 1, и вы можете удалить с помощью rm "$ 1"
, даже если он содержит символы новой строки и пробелы.
find команда также может использоваться для выполнения встроенного теста basename / dirname внутри вашего скрипта, но это более продвинутая тема.
IFS
вам нужно использовать set -f
, чтобы отключить глобусы (обычно имена файлов Windows не содержат символов подстановки, я тоже не должен содержать новые строки, поэтому вы не можете полагаться на это здесь). @ c.sokun: отдельный сценарий, безусловно, самый простой способ; вы можете использовать sh -c '...'
, но это требует, чтобы вы были очень уверены в цитировании оболочки (и если бы вы были, вам не нужно было спрашивать).
– Gilles
1 November 2010 в 23:25
для f в $ (find ...);
- плохая практика. См. Ловушку 1 в mywiki.wooledge.org/BashPitfalls для объяснения причины, и mywiki.wooledge.org/BashFAQ/020 тоже видят, как это сделать надлежащим образом ,
– geirha
3 February 2011 в 06:42
exes = (* .exe)
поступит правильно, если вы расширите его, используя "$ {exes [@]}"
.
– Mikel
3 February 2011 в 08:08
Вы действительно можете использовать ( *.exe ) для решения этой проблемы в bash.
Помещение круглых скобок, подобных этому ( и ) вокруг шаблона, означает, что оно будет расширено и сохранено в array.
Затем вы можете перебирать каждый элемент массива, используя что-то вроде этого:
exes=( *.exe )
for exe in "${exes[@]}"; do
echo "'$exe'"
done
Вот полный пример:
$ mkdir 'dir
> with
> spaces'
$ touch 'dir
> with
> spaces/dir
> with
> spaces'
$ touch 'dir
> with
> spaces/other
> file'
$ find .
.
./dir?with?spaces
./dir?with?spaces/dir?with?spaces
./dir?with?spaces/other?file
$ cd 'dir
> with
> spaces'
$ files=( * )
$ for file in "${files[@]}"; do
> echo "'$file'"
> done
'dir
with
spaces'
'other
file'
I может предоставить только полное решение после того, как вы выясните, как выглядит ваша структура каталогов, потому что я не уверен, что current_dir_name делает то, что вы думаете.
Это будет обрабатывать имена файлов, содержащие любой символ, разрешенный в имени файла, включая новые строки.
#!/bin/bash
if (($# != 1)); then
echo >&2 "Usage: $0 directory"
exit 1
fi
while IFS= read -r -d '' file; do
base=${file##*/} dir=${file%/*/*}
if [[ $dir/${base%.exe}/$base -ef $file ]]; then
echo rm "$file"
fi
done < <(find "$1" -type f -name "*.exe" -print0)
См. http://mywiki.wooledge.org/BashFAQ/020 и http: //mywiki.wooledge .org / BashFAQ / 100 для более подробной информации.
Это будет обрабатывать имена файлов, содержащие любой символ, разрешенный в имени файла, включая новые строки.
#!/bin/bash
if (($# != 1)); then
echo >&2 "Usage: $0 directory"
exit 1
fi
while IFS= read -r -d '' file; do
base=${file##*/} dir=${file%/*/*}
if [[ $dir/${base%.exe}/$base -ef $file ]]; then
echo rm "$file"
fi
done < <(find "$1" -type f -name "*.exe" -print0)
См. http://mywiki.wooledge.org/BashFAQ/020 и http: //mywiki.wooledge .org / BashFAQ / 100 для более подробной информации.
Вы действительно можете использовать ( *.exe ) для решения этой проблемы в bash.
Помещение круглых скобок, подобных этому ( и ) вокруг шаблона, означает, что оно будет расширено и сохранено в array.
Затем вы можете перебирать каждый элемент массива, используя что-то вроде этого:
exes=( *.exe )
for exe in "${exes[@]}"; do
echo "'$exe'"
done
Вот полный пример:
$ mkdir 'dir
> with
> spaces'
$ touch 'dir
> with
> spaces/dir
> with
> spaces'
$ touch 'dir
> with
> spaces/other
> file'
$ find .
.
./dir?with?spaces
./dir?with?spaces/dir?with?spaces
./dir?with?spaces/other?file
$ cd 'dir
> with
> spaces'
$ files=( * )
$ for file in "${files[@]}"; do
> echo "'$file'"
> done
'dir
with
spaces'
'other
file'
I может предоставить только полное решение после того, как вы выясните, как выглядит ваша структура каталогов, потому что я не уверен, что current_dir_name делает то, что вы думаете.
Это будет обрабатывать имена файлов, содержащие любой символ, разрешенный в имени файла, включая новые строки.
#!/bin/bash
if (($# != 1)); then
echo >&2 "Usage: $0 directory"
exit 1
fi
while IFS= read -r -d '' file; do
base=${file##*/} dir=${file%/*/*}
if [[ $dir/${base%.exe}/$base -ef $file ]]; then
echo rm "$file"
fi
done < <(find "$1" -type f -name "*.exe" -print0)
См. http://mywiki.wooledge.org/BashFAQ/020 и http: //mywiki.wooledge .org / BashFAQ / 100 для более подробной информации.
Вы действительно можете использовать ( *.exe ) для решения этой проблемы в bash.
Помещение круглых скобок, подобных этому ( и ) вокруг шаблона, означает, что оно будет расширено и сохранено в array.
Затем вы можете перебирать каждый элемент массива, используя что-то вроде этого:
exes=( *.exe )
for exe in "${exes[@]}"; do
echo "'$exe'"
done
Вот полный пример:
$ mkdir 'dir
> with
> spaces'
$ touch 'dir
> with
> spaces/dir
> with
> spaces'
$ touch 'dir
> with
> spaces/other
> file'
$ find .
.
./dir?with?spaces
./dir?with?spaces/dir?with?spaces
./dir?with?spaces/other?file
$ cd 'dir
> with
> spaces'
$ files=( * )
$ for file in "${files[@]}"; do
> echo "'$file'"
> done
'dir
with
spaces'
'other
file'
I может предоставить только полное решение после того, как вы выясните, как выглядит ваша структура каталогов, потому что я не уверен, что current_dir_name делает то, что вы думаете.
Это будет обрабатывать имена файлов, содержащие любой символ, разрешенный в имени файла, включая новые строки.
#!/bin/bash
if (($# != 1)); then
echo >&2 "Usage: $0 directory"
exit 1
fi
while IFS= read -r -d '' file; do
base=${file##*/} dir=${file%/*/*}
if [[ $dir/${base%.exe}/$base -ef $file ]]; then
echo rm "$file"
fi
done < <(find "$1" -type f -name "*.exe" -print0)
См. http://mywiki.wooledge.org/BashFAQ/020 и http: //mywiki.wooledge .org / BashFAQ / 100 для более подробной информации.
Вы действительно можете использовать ( *.exe ) для решения этой проблемы в bash.
Помещение круглых скобок, подобных этому ( и ) вокруг шаблона, означает, что оно будет расширено и сохранено в array.
Затем вы можете перебирать каждый элемент массива, используя что-то вроде этого:
exes=( *.exe )
for exe in "${exes[@]}"; do
echo "'$exe'"
done
Вот полный пример:
$ mkdir 'dir
> with
> spaces'
$ touch 'dir
> with
> spaces/dir
> with
> spaces'
$ touch 'dir
> with
> spaces/other
> file'
$ find .
.
./dir?with?spaces
./dir?with?spaces/dir?with?spaces
./dir?with?spaces/other?file
$ cd 'dir
> with
> spaces'
$ files=( * )
$ for file in "${files[@]}"; do
> echo "'$file'"
> done
'dir
with
spaces'
'other
file'
I может предоставить только полное решение после того, как вы выясните, как выглядит ваша структура каталогов, потому что я не уверен, что current_dir_name делает то, что вы думаете.
Это будет обрабатывать имена файлов, содержащие любой символ, разрешенный в имени файла, включая новые строки.
#!/bin/bash
if (($# != 1)); then
echo >&2 "Usage: $0 directory"
exit 1
fi
while IFS= read -r -d '' file; do
base=${file##*/} dir=${file%/*/*}
if [[ $dir/${base%.exe}/$base -ef $file ]]; then
echo rm "$file"
fi
done < <(find "$1" -type f -name "*.exe" -print0)
См. http://mywiki.wooledge.org/BashFAQ/020 и http: //mywiki.wooledge .org / BashFAQ / 100 для более подробной информации.
Вы действительно можете использовать ( *.exe ) для решения этой проблемы в bash.
Помещение круглых скобок, подобных этому ( и ) вокруг шаблона, означает, что оно будет расширено и сохранено в array.
Затем вы можете перебирать каждый элемент массива, используя что-то вроде этого:
exes=( *.exe )
for exe in "${exes[@]}"; do
echo "'$exe'"
done
Вот полный пример:
$ mkdir 'dir
> with
> spaces'
$ touch 'dir
> with
> spaces/dir
> with
> spaces'
$ touch 'dir
> with
> spaces/other
> file'
$ find .
.
./dir?with?spaces
./dir?with?spaces/dir?with?spaces
./dir?with?spaces/other?file
$ cd 'dir
> with
> spaces'
$ files=( * )
$ for file in "${files[@]}"; do
> echo "'$file'"
> done
'dir
with
spaces'
'other
file'
I может предоставить только полное решение после того, как вы выясните, как выглядит ваша структура каталогов, потому что я не уверен, что current_dir_name делает то, что вы думаете.
Вы действительно можете использовать (* .exe)
, чтобы решить эту проблему в bash
.
Помещая скобки, подобные этому (
и )
вокруг шаблона означает, что он будет расширен и сохранен в массиве.
Затем вы можете перебирать каждый элемент массива, используя что-то вроде этого:
exes = (* .exe) для exe в "$ {exes [@]}"; do echo "'$ exe'" done
Вот полный пример:
$ mkdir 'dir & gt; с & gt; пробелы '$ touch' dir & gt; с & gt; пробелы / dir & gt; с & gt; пробелы '$ touch' dir & gt; с & gt; пробелы / другие & gt; file '$ find. , ./dir?with?spaces ./dir?with?spaces/dir?with?spaces ./dir?with?spaces/other?file $ cd 'dir & gt; с & gt; space '$ files = (*) $ для файла в "$ {files [@]}"; do & gt; echo "'$ file'" & gt; done 'dir with spaces' 'other file'
Я могу только предоставить полное решение после того, как вы уточните, как выглядит ваша структура каталогов, потому что я не уверен, что current_dir_name
делает то, что вы думаете.
Это будет обрабатывать имена файлов, содержащие любой символ, разрешенный в имени файла, включая символы новой строки.
#! / bin / bash if (($ #! = 1)); затем echo & gt; & amp; 2 "Usage: $ 0 directory" exit 1 fi while IFS = read -r -d '' file; do base = $ {file ## * /} dir = $ {file% / * / *}, если [[$ dir / $ {base% .exe} / $ base -ef $ file]]; то echo rm "$ file" fi done & lt; & lt; (find "$ 1" -type f -name "* .exe" -print0)
См. http://mywiki.wooledge.org/BashFAQ/020 и http://mywiki.wooledge.org/BashFAQ/100 для дальнейшей разработки.
Вы действительно можете использовать (* .exe)
, чтобы решить эту проблему в bash
.
Помещая скобки, подобные этому (
и )
вокруг шаблона означает, что он будет расширен и сохранен в массиве.
Затем вы можете перебирать каждый элемент массива, используя что-то вроде этого:
exes = (* .exe) для exe в "$ {exes [@]}"; do echo "'$ exe'" done
Вот полный пример:
$ mkdir 'dir & gt; с & gt; пробелы '$ touch' dir & gt; с & gt; пробелы / dir & gt; с & gt; пробелы '$ touch' dir & gt; с & gt; пробелы / другие & gt; file '$ find. , ./dir?with?spaces ./dir?with?spaces/dir?with?spaces ./dir?with?spaces/other?file $ cd 'dir & gt; с & gt; space '$ files = (*) $ для файла в "$ {files [@]}"; do & gt; echo "'$ file'" & gt; done 'dir with spaces' 'other file'
Я могу только предоставить полное решение после того, как вы уточните, как выглядит ваша структура каталогов, потому что я не уверен, что current_dir_name
делает то, что вы думаете.
Это будет обрабатывать имена файлов, содержащие любой символ, разрешенный в имени файла, включая символы новой строки.
#! / bin / bash if (($ #! = 1)); затем echo & gt; & amp; 2 "Usage: $ 0 directory" exit 1 fi while IFS = read -r -d '' file; do base = $ {file ## * /} dir = $ {file% / * / *}, если [[$ dir / $ {base% .exe} / $ base -ef $ file]]; то echo rm "$ file" fi done & lt; & lt; (find "$ 1" -type f -name "* .exe" -print0)
См. http://mywiki.wooledge.org/BashFAQ/020 и http://mywiki.wooledge.org/BashFAQ/100 для дальнейшей разработки.
Вы действительно можете использовать (* .exe)
, чтобы решить эту проблему в bash
.
Помещая скобки, подобные этому (
и )
вокруг шаблона означает, что он будет расширен и сохранен в массиве.
Затем вы можете перебирать каждый элемент массива, используя что-то вроде этого:
exes = (* .exe) для exe в "$ {exes [@]}"; do echo "'$ exe'" done
Вот полный пример:
$ mkdir 'dir & gt; с & gt; пробелы '$ touch' dir & gt; с & gt; пробелы / dir & gt; с & gt; пробелы '$ touch' dir & gt; с & gt; пробелы / другие & gt; file '$ find. , ./dir?with?spaces ./dir?with?spaces/dir?with?spaces ./dir?with?spaces/other?file $ cd 'dir & gt; с & gt; space '$ files = (*) $ для файла в "$ {files [@]}"; do & gt; echo "'$ file'" & gt; done 'dir with spaces' 'other file'
Я могу только предоставить полное решение после того, как вы уточните, как выглядит ваша структура каталогов, потому что я не уверен, что current_dir_name
делает то, что вы думаете.
Это будет обрабатывать имена файлов, содержащие любой символ, разрешенный в имени файла, включая символы новой строки.
#! / bin / bash if (($ #! = 1)); затем echo & gt; & amp; 2 "Usage: $ 0 directory" exit 1 fi while IFS = read -r -d '' file; do base = $ {file ## * /} dir = $ {file% / * / *}, если [[$ dir / $ {base% .exe} / $ base -ef $ file]]; то echo rm "$ file" fi done & lt; & lt; (find "$ 1" -type f -name "* .exe" -print0)
См. http://mywiki.wooledge.org/BashFAQ/020 и http://mywiki.wooledge.org/BashFAQ/100 для дальнейшей разработки.
Вы действительно можете использовать (* .exe)
, чтобы решить эту проблему в bash
.
Помещая скобки, подобные этому (
и )
вокруг шаблона означает, что он будет расширен и сохранен в массиве.
Затем вы можете перебирать каждый элемент массива, используя что-то вроде этого:
exes = (* .exe) для exe в "$ {exes [@]}"; do echo "'$ exe'" done
Вот полный пример:
$ mkdir 'dir & gt; с & gt; пробелы '$ touch' dir & gt; с & gt; пробелы / dir & gt; с & gt; пробелы '$ touch' dir & gt; с & gt; пробелы / другие & gt; file '$ find. , ./dir?with?spaces ./dir?with?spaces/dir?with?spaces ./dir?with?spaces/other?file $ cd 'dir & gt; с & gt; space '$ files = (*) $ для файла в "$ {files [@]}"; do & gt; echo "'$ file'" & gt; done 'dir with spaces' 'other file'
Я могу только предоставить полное решение после того, как вы уточните, как выглядит ваша структура каталогов, потому что я не уверен, что current_dir_name
делает то, что вы думаете.
Это будет обрабатывать имена файлов, содержащие любой символ, разрешенный в имени файла, включая символы новой строки.
#! / bin / bash if (($ #! = 1)); затем echo & gt; & amp; 2 "Usage: $ 0 directory" exit 1 fi while IFS = read -r -d '' file; do base = $ {file ## * /} dir = $ {file% / * / *}, если [[$ dir / $ {base% .exe} / $ base -ef $ file]]; то echo rm "$ file" fi done & lt; & lt; (find "$ 1" -type f -name "* .exe" -print0)
См. http://mywiki.wooledge.org/BashFAQ/020 и http://mywiki.wooledge.org/BashFAQ/100 для дальнейшей разработки.
IFS =
и -print0
будут работать вместе, но они не выглядят, когда я запускаю find. -print0 | в то время как IFS = read -r file; do echo & quot; '$ file' & quot ;; сделал
.
– Mikel
3 February 2011 в 08:16
-d ''
, чтобы сказать, что строки заканчиваются на \ 0
вместо \n
. Исправлено в ответе.
– geirha
3 February 2011 в 14:22
$ '\ 0' [! d0] расширяется до той же самой вещи, что и ''
. Bash записывается на C и внутри, переменные хранятся как C-строки (char []). C-строки заканчиваются NUL-байтом (\ 0). параметр read--d использует первый символ следующего аргумента, который для пустой строки будет NUL-байтом.
– geirha
27 March 2011 в 05:54