Очистить кеш yum, yum очистить все
, а затем yum makecache
, чтобы обновить его.
Если это не помогает, скачайте новый файл определения репозитория CentOS с официального сайта. Поскольку вы используете версию 6, прошло некоторое время с момента ее установки, и определения репозитория в /etc/yum.repos.d
могут указывать не на то место для получения списка зеркал.
Это (как вы заметили )довольно сложно; Я попытаюсь объяснить это. Полезно подумать о последовательности синтаксического анализа/обработки, через которую проходят команды (и ), и посмотреть, что происходит на каждом этапе. В целом процесс выглядит примерно так:
find
ищет файлы и запускает содержимое между " -execdir
" и " ;
" как команды. Обратите внимание, что он заменяет " {}
" совпадающим именем файла, но не выполняет никакого другого синтаксического анализа --, он просто запускает первый аргумент после " -execdir
" в качестве имени команды и передает ему следующие аргументы как его аргументов. bash
и ей передается параметр -c
, она анализирует аргумент сразу после -c
как командную строку (, что-то вроде миниатюрного сценария оболочки ). ], а остальные его аргументы в качестве аргументов этого мини-скрипта -. Хорошо, еще несколько замечаний, прежде чем я углублюсь в это :Я использую BSD find
, которая требует, чтобы каталог для поиска был явно указан, поэтому я буду использовать find. -execdir...
вместо просто find -execdir...
. Я нахожусь в каталоге, содержащем файлы "foo.txt" и "z@$%^; *;echo wheee.jpg" (, чтобы проиллюстрировать риски неправильного использования bash -c
). Наконец, у меня есть короткий скрипт с именем pargs
в моем каталоге двоичных файлов, который печатает свои аргументы (или жалуется, если не получил ).
Теперь давайте попробуем две команды из вашего первого вопроса:
$ find. -execdir pargs "{}" \;
pargs got 1 argument(s): '.'
pargs got 1 argument(s): 'foo.txt'
pargs got 1 argument(s): 'z@$%^;*;echo wheee.jpg'
$ find. -execdir "pargs {}" \;
find: pargs.: No such file or directory
find: pargs foo.txt: No such file or directory
find: pargs z@$%^;*;echo wheee.jpg: No such file or directory
Это соответствует вашим ожиданиям :первое сработало (и, кстати, вы могли бы убрать двойные -кавычки вокруг {}
), а второе не удалось, потому что пробел и имя файла рассматривались как часть имя команды, а не ее аргумент.
Кстати, также можно использовать -exec[dir]... +
вместо -exec[dir] \;
--, это говорит find
запускать команду как можно меньше раз и передавать сразу несколько имен файлов:
$ find. -execdir pargs {} +
pargs got 3 argument(s): '.' 'foo.txt' 'z@$%^;*;echo wheee.jpg'
На этот раз я буду выбирать варианты по одному:
$ find. -execdir bash -c "pargs" "{}" \;
pargs didn't get any arguments
pargs didn't get any arguments
pargs didn't get any arguments
«А», говоришь? Здесь происходит то, что bash
запускается со списком аргументов вроде "-c
", "pargs
", "foo.txt
". Опция -c
указывает bash
запустить свой следующий аргумент ("pargs" )как миниатюрный сценарий оболочки, что-то вроде этого:
#!/bin/bash
pargs
...и сортировка -передает этот "мини--скрипт" аргумент "foo.txt" (подробнее об этом позже ). Но этот мини-скрипт -ничего не делает со своими аргументами (s )--, он не передает их команде pargs
, поэтому pargs
ничего не видит. (Я расскажу, как правильно это сделать, в третьем вопросе. )Теперь давайте попробуем второй вариант второго вопроса:
$ find. -execdir bash -c "pargs {}" \;
pargs got 1 argument(s): '.'
pargs got 1 argument(s): 'foo.txt'
pargs got 1 argument(s): 'z@$%^'
bash: foo.txt: command not found
wheee.jpg
Теперь что-то вроде работает, но только вроде. bash
запускается с аргументами " -c
" и "pargs " + имя файла, что работает, как и ожидалось, для "." и "foo.txt", но когда вы передаете bash
аргументы "-c
" и "pargs z@$%^;*;echo wheee.jpg
", он теперь запускает эквивалент этого в виде мини-скрипта -:
#!/bin/bash
pargs z@$%^;*;echo wheee.jpg
Таким образом, bash разделит это на три команды, разделенные точкой с запятой:
pargs z@$%^
" (которые вы видите эффект)*
", который расширяется до слов "foo.txt
" и "z@$%^;*;echo wheee.jpg
",и, следовательно, пытается запустить foo.txt
как команду и передать ей другое имя файла в качестве аргумента. Команды с таким именем нет, поэтому выдает соответствующую ошибку. echo echo wheee.jpg
", вполне разумная команда, и, как вы видите, она выводит на терминал "wheee.jpg". Таким образом, это работало для файла с простым именем, но когда он столкнулся с именем файла, содержащим синтаксис оболочки, он начал пытаться выполнить части имени файла. Вот почему такой способ ведения дел не считается безопасным.
Опять же, я буду рассматривать варианты по одному:
$ find. -execdir bash -c "pargs \"$@\"" {} \;
pargs got 1 argument(s): ''
pargs got 1 argument(s): ''
pargs got 1 argument(s): ''
$
Опять же, я слышу, как вы говорите: «А????» Большая проблема здесь заключается в том, что $@
не экранируется и не заключен в одинарные -кавычки, поэтому он расширяется текущим контекстом оболочки до того, как будет передан в find
. Я буду использовать pargs
, чтобы показать, что find
на самом деле получает здесь в качестве аргументов:
$ pargs. -execdir bash -c "pargs \"$@\"" {} \;
pargs got 7 argument(s): '.' '-execdir' 'bash' '-c' 'pargs ""' '{}' ';'
Обратите внимание, что $@
просто исчез, потому что я запускал это в интерактивной оболочке, которая не получала никаких аргументов (и не устанавливала их с помощью set
команды ). Таким образом, мы запускаем этот мини-скрипт -:
#!/bin/bash
pargs ""
...что объясняет, почему pargs
получал единственный пустой аргумент.
Если бы это было в сценарии, который имел полученные аргументы, все было бы еще более запутанным. Экранирование (или одиночное -цитирование )$
решает эту проблему, но все еще не совсем работает:
$ find. -execdir bash -c 'pargs "$@"' {} \;
pargs didn't get any arguments
pargs didn't get any arguments
pargs didn't get any arguments
Проблема здесь в том, что bash
обрабатывает следующий аргумент после мини-скрипта -как имя мини-скрипта -(, которое доступно для мини-скрипта -как $0
, но не включено в $@
), не как обычный аргумент (, т.е.$1
).Вот обычный скрипт для демонстрации этого:
$ cat argdemo.sh
#!/bin/bash
echo "My name is $0; I received these arguments: $@"
$./argdemo.sh foo bar baz
My name is./argdemo.sh; I received these arguments: foo bar baz
Теперь попробуйте это с похожим bash -c
мини -скриптом:
$ bash -c 'echo "My name is $0; I received these arguments: $@"' foo bar baz
My name is foo; I received these arguments: bar baz
Стандартный способ решить эту проблему — добавить фиктивный скрипт -имя-аргумент (, например «bash» ), чтобы фактические аргументы отображались обычным образом:
$ bash -c 'echo "My name is $0; I received these arguments: $@"' mini-script foo bar baz
My name is mini-script; I received these arguments: foo bar baz
Это именно то, что делает ваш второй вариант, передавая «bash» в качестве имени скрипта и найденное имя файла как$1
:
$ find. -execdir bash -c 'pargs "$@"' bash {} \;
pargs got 1 argument(s): '.'
pargs got 1 argument(s): 'foo.txt'
pargs got 1 argument(s): 'z@$%^;*;echo wheee.jpg'
Что, наконец, работает --по-настоящему, даже для файлов со странными именами. Вот почему этот (или первый вариант в вашем первом вопросе )считается хорошим способом использования find -exec[dir]
. Вы также можете использовать это с методом -exec[dir]... +
:
$ find. -execdir bash -c 'pargs "$@"' bash {} +
pargs got 3 argument(s): '.' 'foo.txt' 'z@$%^;*;echo wheee.jpg'