Если имя уже в нижнем регистре, как вы видели, оно будет передано команде mv дважды.
Если последний аргумент mv является каталогом, он будет рассматриваться как каталог назначения, в который должны быть перемещены все другие именованные объекты.
mv test test
сначала проверит последний аргумент, существует ли он, и если да, то является ли он каталогом. В этом случае это так, поэтому mv проверит, является ли это той же точкой монтирования (если это не так, то есть местом назначения является другое устройство, ему нужно будет скопировать файл, а затем удалить оригинал); в этом случае это так. Таким образом, mv создает последовательность системных вызовов rename(2)
, добавляя все имена источников по очереди в каталог, указанный в качестве места назначения: mv a b c d/
будет генерировать rename("a", "d/a")
, rename("b", "d/b")
и rename("c", "d/c")
- поэтому, конечно, mv test test
будет пытаться вызвать rename("test", "test/test");
, Что, очевидно, является ошибкой, вы не можете переместить каталог внутри себя.
Чтобы решить вашу проблему, сделайте команду mv условной, чтобы новое имя было другим и не существовало (если у вас есть два разных файла с именами "Тест" и "Тест", вы, вероятно, не захотите заменить второй без запроса). Если бы я не проверил это и не набрал его на телефоне, это будет выглядеть примерно так: new="$(echo "$old" | tr ...)"; [[ $new != $old && ! -e $new ]] && mv "$old" "$new"
(смотрите кавычки, вы не хотите, чтобы пробелы в именах давали вам метафорические слова).