jak zmienić nazwę plików podczas kopiowania?

12

Jak mam skopiować (styl archiwizacji, w którym data nie jest zmieniana) wszystkie pliki z katalogu kopii zapasowej do katalogu użytkownika podczas zmiany nazwy każdego pliku, aby usunąć losową część ciągu z nazwy (tj. -2b0fd460_1426b77b1ee_-7b8e)?

cp z:

/backup/path/data/Erp.2014.02.16_16.57.03-2b0fd460_1426b77b1ee_-7b8e.etf

do:

/home/user/data/Erp.2014.02.16_16.57.03.etf

Każdy plik zawsze zaczyna się od „Erp”. po którym następuje ciąg znacznika daty i godziny, po którym następuje ciąg losowy, a następnie rozszerzenie „.etf”. Chcę zachować wszystkie elementy nazwy, w tym znacznik daty i godziny. Chcę tylko usunąć losowy ciąg.

Losowy ciąg umożliwia wielokrotne tworzenie kopii zapasowych tego samego pliku. Jednak w tym przypadku właśnie uruchomiłem fdupes i nie ma duplikatów. Więc mogę po prostu przywrócić wszystkie pliki, usuwając losowy ciąg.

Szukam komendy bash w jednym wierszu, aby to zrobić.

Jeśli to nie zadziała, mógłbym to zrobić w dwóch lub więcej krokach. Zwykle używam KRename, ale w tym przypadku muszę to zrobić w bash. (Pracuję zdalnie.)

MountainX
źródło

Odpowiedzi:

7

paxmoże zrobić to wszystko na raz. Mógłbyś:

cd /backup/path/data && pax -wrs'/-.*$/.etf/' Erp*etf /home/user/data

paxdomyślnie zachowuje czasy, ale można dodać, -peaby zachować wszystko (najlepiej zrobić jako root) lub -ppzachować uprawnienia, np .:

cd /backup/path/data && pax -wrs'/-.*$/.etf/' -pe Erp*etf /home/user/data

W przeciwnym razie ( paxzazwyczaj nie jest dostępny domyślnie), na pewno lepiej jest wykonać kopię niż rename:

cp -a /backup/path/data/Erp*.etf /home/user/data
rename 's/-.*$/.etf/' /home/user/data/Erp*.etf

W ten sposób dla każdego pliku nie jest uruchamiany inny proces.

Graeme
źródło
1
Widzę, że muszę się z tym zapoznać pax. To wygląda na bardzo przydatne narzędzie. Zastanawiam się, dlaczego nie jest standardem w większej liczbie dystrybucji ...
MountainX
@MountainX, Dobre pytanie, według Wikipedii, paxznajduje się w Linuksowej Standardowej Bazie od 2005 roku. Dodatkowo, GNU cpiojest alternatywą dla tego, być może najmniej funkcjonalnym narzędziem GNU na rynku.
Graeme
1
+1 za ostatnie rozwiązanie. W ten sposób dla każdego pliku nie jest uruchamiany inny proces. Ale rename w Fedorze / Red Hat jest inaczej: nie wiem, jak go użyć w tym przypadku.
erik
15

Możesz użyć cppolecenia z -aopcją

-a, --archive
       same as -dR --preserve=all

A następnie użyj pętli for, aby zmienić nazwę wszystkich plików podczas kopiowania:

for file in Erp*etf; do
  cp -a $file destinationDirectory/${file%%-*}.etf
done

Gotowy. Uruchom to polecenie w katalogu źródłowym.

Objaśnienie:%%-* odetnie wszystkie znaki po pierwszym występowania myślnikiem / minus -, a .etfna koniec znowu dodaje rozszerzenie pliku.

Cóż, i jako jedna wkładka, umieść to wszystko w jednej linii. :-) Lubię to

for file in Erp*etf; do cp -a $file destinationDirectory/${file%%-*}.etf; done
erik
źródło
1
Dzięki, czy mógłbyś podać dokumentację %%-*napiwku? Jestem ciekawy.
soyuka
3

W Zsh użyj zmv. Umieść to w .zshrc:

autoload -U zmv
alias zcp='zmv -C'
alias zln='zmv -L'

Następnie użyj

zcp '/backup/path/data/(*)-[0-9A-Fa-f_]#.(*)' '/home/user/data/$1$2'

W bash:

zsh -c 'autoload zmv; zmv -C $0 $1' '/backup/path/data/(*)-[0-9A-Fa-f_]#.(*)' '/home/user/data/$1$2'

Jeśli nie masz zsh, sposób POSIX używa pax (kopiuje katalogi rekurencyjnie).

Jeśli korzystasz z systemu z ograniczeniami bez Zsh i Pax, możesz użyć pętli:

for source in /backup/path/data/*-*.etf; do
  basename=${source##*/}
  cp "$source" "/home/user/data/${basename%-*}.${basename##*.}"
done
Gilles „SO- przestań być zły”
źródło
1

cpnie ma takiej możliwości. Pamiętam, cpioże mogłem to zrobić, ale obecna strona podręcznika mówi inaczej. Jednak (gnu) tarma --transformopcję:

 --transform, --xform EXPRESSION
       use sed replace EXPRESSION to transform file names

Więc miałbyś cmdline jak:

(cd /backup/path/data; tar --create --transform 's/-.*-....//' .) | (cd /home/user/data; tar --extract)
Ricky Beam
źródło