2017-01-12 13 views
-1

можно удалить расширение файлов, если я знаю расширения, например, для удаления .txt из файлов:Как удалить неизвестные расширения файлов из файлов с помощью сценария

foreach file (`find . -type f`) 
    mv $file `basename $file .txt` 
end 

Однако, если я не знаю, какие расширение файла для начала, как бы я это сделал?

Я пробовал:

foreach file (`find . -type f`) 
mv $file `basename $file .*` 
end 

, но это не будет работать.

+0

Есть ли дополнительные «.» S в именах файлов? Если нет, я бы попробовал '' 'файл foreach (find. -type f) set newfile =' файл базы данных | awk 'BEGIN {FS = "."} {print $ 1}' ' mv $ file $ newfile end''' – eclark

+0

Какую оболочку вы используете? Csh? Вы можете получить более эффективные ответы, если вы пометили его правильным тегом ([tag: csh]), предполагая, что я правильно определил его. Я отредактировал тег для вас - исправьте, если я ошибаюсь. –

+0

@IanChang: У вас есть *, чтобы сделать это в csh? Csh [не очень удобно] (https://www-uxsup.csx.cam.ac.uk/misc/csh.html) для программирования. – user1934428

ответ

1

Какая оболочка это? По крайней мере, в Баш вы можете сделать:

find . -type f | while read -r; do 
    mv -- "$REPLY" "${REPLY%.*}" 
done 

(Обычные предостережений применяются: Это не обрабатывает файлы, имена которых содержат символы новой строки.)

+0

Не работает в csh. – Carpetsmoker

+0

@Carpetsmoker Правда, но я никогда не утверждал, что это было, и когда я написал этот ответ, в вопросе не упоминалась какая-либо конкретная оболочка. – melpomene

+0

Хорошо, справедливо :-) Не проверял всю историю вопроса, но в целом вопросы csh имеют привычку накапливать ответы bash ;-) – Carpetsmoker

2

Вы можете использовать СЭД, чтобы вычислить базовое имя файла.

foreach file (`find . -type f`) 
    mv $file `echo $file | sed -e 's/^\(.*\)\.[^.]\+$/\1/'` 
end 
+0

Почему не просто 's /\.[^.]\+$// '? – melpomene

+0

Я согласен, чтобы сократить расширение еще лучше. –

1

Будьте осторожны: Команда вы стремитесь работать может привести к потере данных!

Если вы не считаете, что ваши имена файлов содержат символы новой строки или двойные кавычки, то вы можете использовать:

find . -type f -name '?*.*' | 
sed 's/\(.*\)\.[^.]*$/mv "&" "\1"/' | 
sh 

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

Очевидно, вы проверите это первым, исключив часть | sh. Попробуйте запустить его с помощью | sh -x, чтобы узнать, что делает оболочка. Подумайте о том, чтобы убедиться, что вы захватили вывод оболочки, стандартный вывод и стандартную ошибку, в файл журнала, чтобы у вас была запись об ущербе, который произошел.

Удостоверьтесь, что у вас есть резервная копия исходного набора файлов до, вы начинаете играть с этим. Это должен быть только файл tar, хранящийся в другой части иерархии каталогов, и вы можете удалить его, как только будете довольны результатами.

Вы можете выбрать любую оболочку; это не зависит от каких-либо конструкций оболочки, кроме труб и одинарных кавычек и двойных кавычек (довольно часто встречающихся для всех оболочек), а сценарий sed также является нейтральным версией.

Обратите внимание, что если у вас есть файлы xyz.c и xyz.h, прежде чем запустить это, вы будете иметь только файл xyz после этого (и то, что она содержит, зависит от порядка, в котором обрабатываются файлы, которые не обязательно должны быть алфавитный порядок).

Если вы считаете, что имена ваших файлов могут содержать двойные кавычки (но не одинарные кавычки), вы можете играть с изменением котировок в сценарии sed. Если вам, возможно, придется иметь дело с обоими, вам нужен более сложный сценарий sed. Если вам нужно иметь дело с новыми символами в именах файлов, то пришло время (а) сообщить, что ваш пользователь (ы) перестает быть глупым и (b) исправляет имена, чтобы они не содержали символы новой строки. Затем вы можете использовать сценарий выше.Если это не представляется возможным, вы должны работать много сложнее получить работу точно - вы, вероятно, необходимо убедиться, что у вас есть find, который поддерживает -print0, sed, который поддерживает -z и xargs, который поддерживает -0 (установка последних версий GNU, если у вас еще нет нужной поддержки).

1

Это очень просто:

$ set filename=/home/foo/bar.dat 
$ echo ${filename:r} 
/home/foo/bar 

Смотреть еще в man tcsh, в "Истории замещения":

г

Удалить расширение имени файла '.xxx', в результате чего корневое имя ,