2017-02-01 24 views
2

Я пытаюсь массово переименовать некоторые файлы, обрезая файлы, в которых первое место происходит в имени файла. Я написал простой скрипт, чтобы сделать это с помощью переименования, как, например:/usr/bin/rename: слишком длинный список аргументов (массовое переименование файлов)

for i in *.fa; do rename 's/\s.*//' *.fa; done 

Это прекрасно работает в тесте и дает следующие результаты, как желательные:

$:~/testenv$ ls 
NM_000016.5_LastMex1_4_12 23 0 1 KB882088_3062975-30.fa NM_000016.5_PastMex1_4_12 23 0 1 KB882088_3062975-30.fa 
$:~/testenv$ for i in *.fa; do rename 's/\s.*//' *.fa; done 
$:~/testenv$ ls 
NM_000016.5_LastMex1_4_12 NM_000016.5_PastMex1_4_12 

К сожалению, я должен сделать это много файлов, около 6,7 миллионов. Это дает мне следующее сообщение об ошибке:

/usr/bin/rename: Argument list too long 

Я пытался всякого рода трюк я могу думать, даже когда я использую его найти не могу подобрать файлы.

$:~/testenv$ ls 
NM_000016.5_astMex1_4_12 23 0 1 KB882088_3062975-30.fa NM_000016.5_PastMex1_4_12 23 0 1 KB882088_3062975-30.fa 
NM_000016.5_LastMex1_4_12 23 0 1 KB882088_3062975-30.fa  
$:~/testenv$ find . -maxdepth 1 -type f -exec sh -c 'rename 's/\s.*//' *.fa' _ {} \; 
find: `./NM_000016.5_PastMex1_4_12 23 0 1 KB882088_3062975-30.fa': No such file or directory 
find: `./NM_000016.5_astMex1_4_12 23 0 1 KB882088_3062975-30.fa': No such file or directory 

Любая помощь была бы принята с благодарностью.

+2

'для г в * .fa; do rename 's/\ s. * //' * .fa; done', когда он работает, переименовывает все ваши .fa-файлы * один раз для каждого файла *, то есть, если у вас 1000 файлов, вы переименовываете все 1000 файлов в 1000 раз, в общей сложности 1,000,000 потенциальных операций. Наверняка, это не то, что вы хотите. –

+0

Эти примеры 'ls' будут легче читать, если их заменить примерами' ls -1Q'. ('-1Q' перечисляет по одному элементу в строке, * цитируется *.) – agc

+0

@agc, ... хотя это расширение не-POSIX, нет гарантии, что OP (или кто-либо еще) имеет его доступным. –

ответ

4

У вас есть эта ошибка, потому что вы используете *.fa не только как Глобо перебрать, но и расширить его в командной строке отдельного rename команды, где этот список имен перерасхода максимальной длиной аргумента вектора вашей операционной системы. Вы не будете иметь эту проблему со следующим:

# run rename once per *.fa file, with only one name given each run 
for i in *.fa; do rename 's/\s.*//' "$i"; done 

... или его более эффективным кузена:

# only tries to rename files that actually have a space in their name 
# runs "rename" only as many times as necessary -- not once per file, like the above. 
find . -name '*[[:space:]]*.fa' -exec rename 's/\s.*//' {} + 

Тем не менее, не является строго обязательным внешний rename команда для этого случай использования совсем.

# Rename all files with a space in their name, then ending in .fa, to truncate at the space 
for i in *[[:space:]]*.fa; do 
    mv -- "$i" "${i%%[[:space:]]*}" 
done 

Если вы хотите сохранить расширение, что вместо этого может быть:

for i in *[[:space:]]*.fa; do 
    mv -- "$i" "${i%%[[:space:]]*}.fa" 
done 
+0

Неужели вы не хотите выполнять 'mv' 6,7 миллиона раз? Разве это не повод, чтобы придерживаться 'find -exec rename {} +'? –

+0

@MarkSetchell, ах, но действительно ли это 6,7 млн. Файлов, которые нужно * переименовать? Я предполагаю, что мы передавали много имен для «переименования», которые были уже прекрасны, поэтому улучшаем glob, чтобы искать только имена с пробелом в них. –

+0

@ charles-duffy эй спасибо, ваше решение работает очень хорошо. Одна вещь, которая произошла, это то, что я получил ошибку «пустое место на устройстве» в середине ее на нескольких файлах. Что странно, потому что у меня есть космическое пространство. Есть идеи? '/ dev/dm-0 17T 252G 16T 2% /' – bhffs