Czy istnieje komenda linux jak mv, ale z wyrażeniem regularnym?

41

Na przykład chcę mv (.*?).sql $1.php,

czy istnieje polecenie, które pozwala mi określić wzorce zmiany nazwy?

JoshRibs
źródło

Odpowiedzi:

32

Jak już wspomnieli inni, renamejest w tym dobry, ale man renameprzed wypróbowaniem przeczytaj stronę man ( ). Istnieją co najmniej dwa zupełnie różne narzędzia o nazwie, renamektóre z nich będą zależeć od twojej dystrybucji. Niepoprawne wywoływanie ich może być niebezpieczne.

Oto strona podręcznika użytkownika dla wersji opartej na perlu autorstwa Larry'ego Walla, która jest dostarczana z Ubuntu. Nadajesz mu perlowe wyrażenierename 's/\.sql$/.php/' *.sql

Oto strona podręcznika man dla zmiany nazwy, która jest dostarczana ze starszymi dystrybucjami Red Hat i CentOS. Użycie jest takie jak proste zastąpienie łańcucharename .sql .php *.sql

Możesz także użyć pojedynczej linijki bash do przetworzenia każdego pliku po jednym:

$ for f in *.sql; do mv -i "$f" "${f%%.*}.php"; done
Ryan Bright
źródło
Czy ktoś może przesłać plik binarny Windows dla zmiany nazwy opartej na perlu?
Mcandre
Zmiana nazwy wersji Perla nie może przenosić plików z jednego systemu plików do innego.
lilydjwg
bash one-liner jest pomocny, zwłaszcza gdy nie ma żadnej renamefunkcji (np. busybox)
artm
10

Jest taki rename(1), który nie używa wyrażeń regularnych, ale może rozwiązać problem:

rename .sql .php *.sql

Jest też mmv(1), ale nie jestem zaznajomiony z tym, jak to działa.

Adam Rosenfield
źródło
W Ubuntu i Debianie (nie jestem pewien co do innych dystrybucji), domyślnie /usr/bin/renamelinki do /usr/bin/prename, które wymagają wyrażeń regularnych.
ℝaphink
5

Dzień dobry

Możesz także spróbować wejść

for i in $(\ls -d *.sql)
do
mv $i $(echo $i | sed -e 's/\.sql$/\.php/')
done

Lub, aby użyć regex, zmień go nieco na

for i in $(\ls -d | egrep -e '.*\.sql')
do
mv $i $(echo $i | sed -e 's/\.sql$/\.php/')
done

dla odrobiny zabawy z kodowaniem powłoki. (-:

Rob Wells
źródło
2
Nie udaje się to w przypadku plików zawierających spacje w nazwie, więc bądź ostrożny. Nigdy niels należy analizować danych wyjściowych .
slhck,
Ten sedprzykład jest jednak całkiem dobry.
jasna gwiazda
2

Jako hydraulik lubię fajki :)

Uwaga: ta odpowiedź jest pełna - jako nowicjusz doceniam ją, gdy ktoś, kto zna, poświęca czas na wyjaśnienie, więc płacę „do przodu”. Jeśli nie jesteś nowicjuszem, przepraszam za długość i gadatliwość.

ls -1 *_201[67][0-9]* | sed -e 's/\(\(.\+\)[-_]\(201[67][0-9]\{4\}\)\([^.]\+\)\?\.[0-9a-z]\{2,3\}\)/mkdir -p \2\/\3; mv \1 \2\/\3\/\1/' | bash

Gdzie:

ls -1 *_201[67][0-9]*

wyświetla wszystkie pliki pasujące do wzorca, w tym przypadku szukam plików z datą w nazwie pliku w postaci „RRRRMMDD”

sed -e 's/\(\(.\+\)[-_]\(201[67][0-9]\{4\}\)\([^.]\+\)\?\.[0-9a-z]\{2,3\}\)/mkdir -p \2\/\3; mv \1 \2\/\3\/\1/'
#        : | |    |     |                  | |       |                    |:                                 :
#        : |^2....^    ^3..................^^4.......^                    |:                                 :
#        :^1..............................................................^:                                 :
#        /................filename.................pattern................./...mkdir...and....mv...command.../

^ 1: 1. grupa przechwytywania - cała nazwa pliku

^ 2: 2. grupa przechwytywania - pierwsza część wzorca nazwy pliku

^ 3: 3. grupa przechwytywania - druga część nazwy pliku - tutaj data „RRRRMMDD”

^ 4: 4. grupa przechwytywania - opcjonalna część nazwy pliku między datą a rozszerzeniem oraz samym rozszerzeniem

Sooooo .... jeśli mam plik o nazwie

CallLog_555123412_20161231-214403.7z

...następnie

mkdir -p \2\/\3; mv \1 \2\/\3\/\1

właściwie znaczy

# make directory and sub-directory
mkdir -p CallLog_555123412/20161231
# move file from current directory to sub-sub-directory just created
mv CallLog_555123412_20161231-214403.7z CallLog_555123412/20161231/CallLog_555123412_20161231-214403.7z

Zauważ, że dane wyjściowe polecenia sed są przesyłane do „bash”, aby je wykonać. Aby najpierw zobaczyć proponowane ruchy plików BEZ faktycznego ich przenoszenia, najpierw usuń „| bash ”na końcu i spróbuj tak:

ls -1 *_201[67][0-9]* | sed -e 's/\(\(.\+\)[-_]\(201[67][0-9]\{4\}\)\([^.]\+\)\?\.[0-9a-z]\{2,3\}\)/mkdir -p \2\/\3; mv \1 \2\/\3\/\1/'

Nie spowoduje to żadnych zmian, ale zobaczysz polecenie, które zostanie wykonane, jeśli uruchomisz je z '| bash 'oznaczony na końcu.

Jest to przydatne, ponieważ możesz utworzyć dowolne podkatalogi z części w nazwie pliku lub cokolwiek innego, co dodasz do tekstu „zastępczego” w poleceniu sed. Pamiętaj jednak, że sed wymaga wielu znaków ucieczki.

Wsporniki SED Regex:

(...) wymagają zmiany znaczenia dla grupowania przechwytywania -> \ (... \)

{m, n} wymagają zmiany znaczenia dla kwantyfikacji poprzedniego obiektu -> \ {m, n \}

/ wymaga zmiany znaczenia w ciągu zastępującym -> \ /

[...] NIE wymagają ucieczki dla klas postaci

\ 1 w zastępującym ciągu odnosi się do 1. przechwyconej grupy i tak dalej ...

OSTRZEŻENIE DOTYCZĄCE BEZPIECZEŃSTWA: NIGDY NIE NALEŻY PRZEWODZAĆ, ABY „uderzyć”, JEŚLI W PEŁNI NIE ZROZUMIE WYNIKÓW

Mam nadzieję, że pomoże to usunąć niektóre blokady :)

skeetastax
źródło
1

Zainstaluj mmv, a następnie wykonaj następujące czynności:

mmv "*.sql" "#1.php"
Gepsens
źródło