одно и то же имя файла в нескольких каталогах: как назначить им разные имена одновременно с помощью только одной команды?

sed 's/123/456/g; w number123' number

Обратите внимание, что он печатает (и записывает в number123 ) все строки, включая те, которые не содержат 123 .

Чтобы распечатать только измененные:

sed -e 's/123/456/gw number123' -e t -e d number
1
27.12.2018, 00:52
5 ответов

Предполагая, что все ваши каталоги находятся в одном родительском элементе, попробуйте следующее:

$ for f in $(ls */accepted_hits.bam); do mv $f $(dirname $f)/$(dirname $f)-$(basename $f); done
1
29.04.2021, 00:28

Я бы, вероятно, использовал awk , но это просто вопрос вкуса, а не правильного и неправильного:

find . -name accepted_hits.bam | awk '{ print "cp -pi \"" $0 "\" \"" $0 "\"_" NR "; mv -i \"" $0 "\"_" NR " ./bam-files/" }' | tcsh -f

где вам нужно создать каталог ./ bam-files / перед вызовом указанной выше строки или измените имя каталога. Я намеренно использовал -p для сохранения времени файла и -i , чтобы избежать перезаписи, на всякий случай. Итак, перед повторным вызовом команд очистите целевой каталог.

Если вы хотите удалить исходные файлы, замените cp -pi на mv -i .

Сценарий не включает вызовы basename в надежде столкнуться с меньшими проблемами, если имя пути содержит специальные символы (обрабатываются пробелы и большинство специальных символов).

PS: Вы также можете выполнить пробный прогон перед выполнением, не указав | tcsh -cf в конце. Если у вас не установлен tcsh (да, есть Linux без него), не стесняйтесь использовать sh или bash .

0
29.04.2021, 00:28

Если вы просто хотите назвать их уникальными файлами, вы можете использовать переменную RANDOM, как показано ниже:

find /basedir/ -type f -name "accepted_hits.bam" -exec bash -c 'mv $0 $0.$RANDOM' {} +

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

for file in $(find /basedir/ -type f -name "accepted_hits.bam"); do ((count++)) ; mv $file ${file}_${count}; done

Два вышеуказанных метода переименовывают файл в том же каталоге. Если вы хотите переименовать их в другой каталог, вы можете объединить их с ответом @schlimmchen (используя basename и dirname). Вы даже можете вставить оператор echo перед командой move, чтобы увидеть результат без фактического перемещения файлов. Я обнаружил, что это удобный способ протестировать команды, не рискуя внести изменения в файлы.

0
29.04.2021, 00:28

Это очень легко сделать с помощью глобусов оболочки:

  1. Добавьте счетчик в имя ( accept_hits.bam.1 , accept_hits.bam.2 и так далее):

     c = 0; для f в * / accept_hits.bam; do mv "$ f" "$ f". $ ((++ c)); done 
     

    Explanation

    Это просто перебирает все файлы с именем accept_hits.bam , которые находятся в подкаталогах текущего каталога, и сохраняет каждый из них как $ f . Конструкция $ ((++ c)) увеличивает счетчик ( $ c ), поэтому $ f. $ ((++ c)) будет file.1 , file.2 и т. Д., Увеличивается на каждой итерации.

    Обратите внимание, что я использую c = 0 в начале. Если вы этого не сделаете, при последующих запусках будет сохранено значение $ c , и оно будет продолжать увеличиваться.

  2. Добавьте счетчик, но перед расширением ( accept_hits.1.bam , accept_hits.2.bam и так далее):

     c = 0; для f в * / accept_hits.bam; do 
    mv "$ f" "$ (dirname" $ ​​f ")" / "$ (basename" $ ​​f ".bam)". $ ((++ c)).bam 
    done 
     

    Explanation

    Команда dirname возвращает путь к родительскому каталогу файла:

     $ dirname / usr / local / bin / apt 
     / usr / local / bin 
     

    Команда basename обратная, она удаляет каталог, оставляя только последнюю часть пути, а также может удалить extension:

     $ basename /etc/apt/sources.list
    sources.list
    $ basename /etc/apt/sources.list .list ## remove extension 
    sources 
     

    Итак, mv "$ f" "$ (dirname" $ ​​f ")" / "$ (basename" $ ​​f ".bam)". $ ((++ c)) .bam переименует файл по своему усмотрению.

  3. Добавьте имя родительского каталога ( accept_hits.dir1.bam , accept_hits.dir2.bam или любое другое имя вашего каталога)

     для f in * / accept_hits. бац; сделать 
    dir = "$ (dirname" $ ​​f ")"; mv "$ f" "$ dir" / "$ (basename" $ ​​f ".bam)". "$ dir" .bam 
    done 
     

    Пояснение

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

  4. Используйте внешние инструменты. Perl переименует, например, . Стандартное переименование , которое поставляется с дистрибутивами на основе Debian, не может работать с увеличивающимися счетчиками. Однако я нашел этот , который может. Загрузите сценарий, ссылка на который есть на этой странице, сохраните его как increname в текущем каталоге и запустите его следующим образом:

     perl increname -n 's / .bam / ++ $ c. ".bam" / e '* / accept_hits.bam 
     
0
29.04.2021, 00:28

С помощью bash и find

find . -type f -name accepted_hits.bam -exec bash -c \
'i=0; for f; do (( ++i )); mv -- "$f" "${f}_$i"; done' _ {} +
2
29.04.2021, 00:28

Теги

Похожие вопросы