Почему перенаправление оболочки странным образом взаимодействует с find - PullRequest
0 голосов
/ 16 марта 2012

Я хочу добавить файл лицензии в начало каждого файла .java в каталоге * nix и всех его подкаталогов. У меня есть это решение, которое, кажется, работает нормально:

$ cat muppet-license.txt 
// LICENSE: // Manuh-manuh
$ for file in `find . -iname "*.java"`; do 
     cat muppet-license.txt "$file" > "$file.out"; 
     mv "$file.out" "$file";
done

Мой вопрос: почему следующий вызов find НЕ работает:

find . -iname "*.java" -exec sh -c 'cat muppet-license.txt "$1" > "$1"' -- {} \;

Это приводит к тому, что в самом первом найденном файле find "лицензия маппета" неоднократно добавляется в начало - файл, кажется, непрерывно увеличивается без остановки.

Может кто-нибудь объяснить, в чем здесь разница? Это как-то связано с изменением файла с именем $ 1, заставляющим find повторно находить его как часть рекурсивного поиска? У кого-нибудь есть хорошие ссылки на детали алгоритма, который находит использование?

Ответы [ 3 ]

3 голосов
/ 16 марта 2012

Проблема в том, что

cat foo $file > $file

будет делать именно то, что вы говорите, что не всегда очевидно.Первое, что делает оболочка с этой командой, - это открывает $file для записи, обрезая ее до нулевой длины.Затем запускается cat, объединяющий foo и содержимое $file, которое теперь является копией foo в $file.

3 голосов
/ 16 марта 2012

Вы говорите cat читать из того же файла, в который вы пишете:

cat muppet-license.txt "$1" > "$1"

Таким образом, cat будет читать muppet-license.txt и записывать его в $1, а затем читать $1 (чтотеперь содержит лицензию) и снова добавьте лицензию в конец того же файла, затем продолжите чтение того, что было написано и т. д., в бесконечном цикле, повторяя файл лицензии в пределах $1 снова и снова ...

Примерно так должно работать:

find . -iname "*.java" -exec sh -c 'cat muppet-license.txt "$1" > "$1.out"; mv "$1.out" "$1"' -- {} \;

Это позволяет избежать бесконечного цикла, записав лицензию и $1 в отдельный файл $1.out и переместив его обратно в $1 после записи вЭто.Разница не имеет ничего общего с find, только с вызовом sh и cat.

1 голос
/ 17 марта 2012

Проблема не с поиском. То же самое происходит, если вы делаете:

cat muppet-license.txt a.java > a.java

и потому что cat перечитывает данные, которые пишет. Оболочка открывает a.java для записи, обрезая ее до нулевой длины. Затем cat записывает содержимое файла muppet-license.txt в a.java, а затем открывает файл a.java (который теперь является копией muppet-license.txt) и записывает первую строку в конец файла (2-я линия). Затем он читает 2-ю строку и добавляет к ней конец (запись 3-й строки) и непрерывно повторяется.

...