Linux mv-файл із довгим ім'ям


19

У Linux я іноді перейменую такі файли:

mv dir1/dir2/dir3/file.txt  dir1/dir2/dir3/file.txt.old

Зауважте, що я хочу просто перейменувати файл, а не переміщувати його в інший каталог.

Чи є команда, яка дозволила б мені зробити скорочену версію цієї команди? Я думаю про щось на кшталт:

mv dir1/dir2/dir3/file.txt  file.txt.old

а може навіть щось подібне (просто додати ім’я):

mv dir1/dir2/dir3/file.txt  {}.old

Моя мета - не потрібно знову вказувати повний шлях.

Я знаю, що ті "приклади", які я написав, не працюють, але це лише ідея того, що я хочу досягти.

Я не хочу вводити компакт-диски до каталогу.


8
Чому ви не перейдете до каталогу? Це швидко і вирішує вашу проблему.
Майкл Хемптон

Я маю справу з багатьма підкаталогами з цього самого місця, це повільніше, якщо мені доведеться щоразу повертатися до цього батьківського
режисура

3
Ніхто не сказав, що вам доведеться перейти в інший каталог, лише той, який ви хочете.
Майкл Хемптон

Зауважте, що (cd dir1/dir2/dir3 && exec mv file.txt{,.old})фактично така ж продуктивність, як і код без підпроцесу, оскільки ви execуникаєте fork()під час виклику зовнішньої команди, тому у вас є рівно одна форка в будь-якому випадку.
Чарльз Даффі

Відповіді:


45

для одного файлу спробуйте

mv dir1/dir2/dir3/file.{txt,txt.old}

де X{a,b}конструкція розширюється на Xa Xb, ви можете мати попередній перегляд за допомогою

echo dir1/dir2/dir3/file.{txt,txt.old}

щоб побачити, чи відповідає вашим потребам.

Примітка:

  1. що для декількох файлів

    mv dir1/dir2/dir3/file{1,2,3}.{txt,txt.old}
    

навряд чи розшириться до того, що ви хочете. (це розшириться до змішаного файлу file.txt file1.txt.old file2.txt ...)

  1. {txt,txt.old}можна скоротити відповідно до {,.old}коментаря

  2. якщо ім'я каталогів неоднозначне, можна використовувати підстановку.

    mv *1/*2/d*/*.{,old}
    

для багаторазового використання файлів rename

rename -n s/txt/old.txt/ dir1/dir2/dir3/file*.txt 

drop, -nщоб мати ефективне перейменування.


1
приємно, я не знав цього способу розширення! дякую
santiago arizti

14
Чи mv dir1/dir2/dir3/file.txt{,.old}не працювала б і була ще коротшою?
Джош

3
@Josh Так, це прекрасно працює і вимагає меншої кількості натискань клавіш. Я використовую цю конструкцію дуже регулярно.
rlf

2
смішно, як ти можеш використовувати оболонку Linux роками і все ще знаходити нові хитрощі
Сант'яго Арісті

Я здогадуюсь, що всі ці "трюки" були б більш очевидними, якби я пройшов якусь офіційну підготовку з баш-мови, але я просто навчився достатньо ладитись.
santiago arizti

6

Команда renameперейменовує всі відповідні файли. Основна його мета - перейменування декількох файлів, але якщо вираз Perl відповідає лише одному файлу, то він буде перейменовувати лише цей єдиний файл. Для отримання додаткової інформації та дістро синтаксису конкретного ласка прочитайте сторінку керівництва: man rename.

Приклад використання: перейменуйте "/path/file.txt" на "/path/file.txt.old":

rename 's/file.txt/file.txt.old/g' /path/file.txt

Коротше позначення (завдяки шалом):

rename 's/$/.old/' /path/file.txt
rename '$_.=".old"' /path/file.txt

Для сухого ходу використовуйте rename -n.

Більше прикладів та деталей можна знайти на веб-сторінці https://thepcspy.com/read/bulk-rename-files-in-ubuntu/


класно, я знав про команду перейменування, просто ніколи не знав, що це може зробити, дякую!
santiago arizti

6
На жаль, різні дистрибутиви Linux мають різні renameкоманди з абсолютно різною поведінкою.
kasperd

1
Для цього конкретного завдання перейменування шляхом додавання .oldдо імені файлів, можливо, трохи зручніше зробити rename 's/$/.old/' /path/to/file.txtабоrename '$_.=".old"' /path/to/file.txt
shalomb

@Fabian - Мені не доводилося, я просто прагнув "найкоротшої руки" за те, що, здається, часто використовується ідіома, яку шукає ОП :)
shalomb

4

Для разового випадку, якщо я не хочу змінити свою поточну директорію, я можу просто скористатись підзагін:

(cd dir1/dir2/dir3/ && mv file.txt file.txt.old)

Оскільки ви cdзнаходитесь у підколонці, ви не змінили каталог у фактичній оболонці


4
Швидше та безпечніше у використанні && exec mv- таким чином ви не намагатиметесь перейменувати, якщо cdне вдалося , і execспоживає передплату, уникаючи таким чином штрафу за продуктивність.
Чарльз Даффі

Погодьтеся з разовим && випадком, як я вже сказав, я б не турбувався про вартість підрозділу (будьте простим: можливість легко запам'ятати, як це зробити, важливіше IMO)
Адам

Я заперечую, що якщо ви пам’ятаєте лише один спосіб, запам'ятовування ефективного способу допомагає переконатися, що ви не підете неефективним шляхом у випадках, коли це має значення.
Чарльз Даффі

4

Мені подобається рішення @ archemar щодо використання {} розширення, тому що ви можете використовувати його, коли ви вже запустили свій командний рядок. Ось деякі інші можливості для повноти:

F="dir1/dir2/dir3/file.txt" ; mv "$F" "$F.old"

(лапки потрібні лише в тому випадку, якщо в імені є пробіли чи інші символи, що розбивають слова)

mymv() {
    mv "$1/$2" "$1/$3"
}

mymv dir1/dir2/dir3 file.txt file.txt.old
mymv dir5/dir6/dir7 file.txt file.txt.old

Примітки:

  • Це синтаксис bash, можливо, ви використовуєте іншу оболонку
  • mymv може бути будь-який розумний рядок, я використовував mymv для "мого руху".
  • Визначення функції можна поставити у ваш .bash_profile

Інший:

cd dir1/dir2/dir3 ; mv file.txt file.txt.old ; cd -

але

(cd dir1/dir2/dir3/ && exec mv file.txt file.txt.old)

(від @Adam та @CharlesDuffy), напевно, краще, якщо CD виходить з ладу.


1
Не використовуйте mmv, вже існує програма, названа таким чином.
glglgl

1
@glglgl Готово :)
Law29

2

Якщо ви хочете ввести підкаталог для скорочення mvкоманди, але хочете згодом повернутися до поточного каталогу, є два способи зробити це. Один полягає в тому, щоб помістити cdі mvв нижню частину корпусу (як вже було запропоновано).

Інше - використовувати pushdта popdзмінювати каталоги:

pushd dir1/dir2/dir3/; mv file.txt file.txt.old; popd

pushdКоманда , як cd, за винятком того, що першим виштовхує ім'я поточного каталогу в стек. popdвидаляє головне ім'я зі стека та змінює цей каталог.


pushdі popdє розширеннями, призначеними для інтерактивного використання - POSIX явно перераховує їх як "результати не визначені", і оболонка, побудована для запуску сценаріїв (тобто в мінімально вбудованому середовищі), не потребує їх підтримки.
Чарльз Даффі

2

Я б просто зробив

cd dir1/dir2/dir3/
mv file.txt file.txt.old
cd ~- # go to the most recent directory

0

Рішення, що передбачає: mv something{.txt,.txt.old}використовують "башизм". Якщо ви хочете більш портативний спосіб, використовуючи звичайні маніпуляції зі змінними:

# rename all files "file*.txt" of directory /dir1/dir2/dir3 into file*.txt.old:
for f in dir1/dir2/dir3/file*.txt ; do
  mv "$f" "${f/.txt/.txt.old}"  # note there are no terminating "/"
done


# "${var/A/B}" is the content of var with the first occurence of "A" replaced by "B"

2
Дивіться pubs.opengroup.org/onlinepubs/009695399/utilities/… про відповідну специфікацію POSIX - ${var/text/replacement}це сам башизм.
Чарльз Даффі

@CharlesDuffy о ... Ти мене сумуєш :(
Олів'є Дулак,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.