Cel
Zmień te nazwy plików:
- F00001-0708-RG-biasliuyda
- F00001-0708-CS-akgdlaul
- F00001-0708-VF-hioulgigl
do tych nazw plików:
- F0001-0708-RG-biasliuyda
- F0001-0708-CS-akgdlaul
- F0001-0708-VF-hioulgigl
Kod powłoki
Testować:
ls F00001-0708-*|sed 's/\(.\).\(.*\)/mv & \1\2/'
Występować:
ls F00001-0708-*|sed 's/\(.\).\(.*\)/mv & \1\2/' | sh
Moje pytanie
Nie rozumiem kodu seda. Rozumiem, co to polecenie zamiany
$ sed 's/something/mv'
znaczy. I trochę rozumiem wyrażenia regularne. Ale nie rozumiem, co się tutaj dzieje:
\(.\).\(.*\)
lub tu:
& \1\2/
To pierwsze wygląda dla mnie tak, jakby oznaczało: „pojedynczy znak, po którym następuje pojedynczy znak, po którym następuje sekwencja dowolnej długości pojedynczego znaku” - ale z pewnością chodzi o coś więcej. Jeśli chodzi o drugą część:
& \1\2/
Nie mam pojęcia.
bash
shell
sed
file-rename
Daniel Underwood
źródło
źródło
Odpowiedzi:
Po pierwsze, powinienem powiedzieć, że najłatwiej to zrobić, używając poleceń prename lub rename.
W systemie Ubuntu, OSX (pakiet Homebrew, pakiet
rename
MacPortsp5-file-rename
) lub innych systemach ze zmianą nazwy perl (prename):lub w systemach ze zmianą nazwy z util-linux-ng, takich jak RHEL:
To o wiele bardziej zrozumiałe niż równoważne polecenie sed.
Ale jeśli chodzi o zrozumienie polecenia sed, pomocna jest strona podręcznika sed. Jeśli uruchomisz man sed i wyszukasz & (używając polecenia / do wyszukiwania), znajdziesz to specjalny znak w s / foo / bar / replaceements.
s/regexp/replacement/ Attempt to match regexp against the pattern space. If success‐ ful, replace that portion matched with replacement. The replacement may contain the special character & to refer to that portion of the pattern space which matched, and the special escapes \1 through \9 to refer to the corresponding matching sub-expressions in the regexp.
Dlatego
\(.\)
dopasowuje pierwszy znak, do którego można się odwoływać\1
. Następnie.
dopasowuje następny znak, którym jest zawsze 0. Następnie\(.*\)
dopasowuje resztę nazwy pliku, do której można się odwoływać\2
.Ciąg zastępujący łączy to wszystko razem za pomocą
&
(oryginalna nazwa pliku),\1\2
która jest każdą częścią nazwy pliku z wyjątkiem drugiego znaku, który był 0.To dość tajemniczy sposób, IMHO. Jeśli z jakiegoś powodu polecenie rename nie było dostępne i chciałbyś użyć seda do zmiany nazwy (a może robiłeś coś zbyt złożonego do zmiany nazwy?), Bardziej wyraźne wyrażenie w swoim wyrażeniu regularnym uczyniłoby go znacznie bardziej czytelnym. Może coś takiego:
ls F00001-0708-*|sed 's/F0000\(.*\)/mv & F000\1/' | sh
Możliwość zobaczenia, co faktycznie się zmienia w s / wyszukiwaniu / zamianie / sprawia, że jest on znacznie bardziej czytelny. Ponadto nie będzie wysysać znaków z nazwy pliku, jeśli przypadkowo uruchomisz go dwa razy lub coś w tym stylu.
źródło
rename
jest to link o „zmienionej nazwie” . ierename
została „przemianowana” zprename
… np. w Ubuntu:readlink -f $(which rename)
output/usr/bin/prename
…rename
Wspomniany przez Davida program jest zupełnie inny.sh
? jest to potencjalnie niebezpieczne, ponieważ można wykonać dowolny kod (traktujesz dane jako kod).miałeś już wyjaśnienie seda, teraz możesz używać tylko powłoki, nie potrzebujesz zewnętrznych poleceń
for file in F0000* do echo mv "$file" "${file/#F0000/F000}" # ${file/#F0000/F000} means replace the pattern that starts at beginning of string done
źródło
Napisałem mały post z przykładami zmiany nazwy partii, używając
sed
kilka lat temu:http://www.guyrutenberg.com/2009/01/12/batch-renaming-using-sed/
Na przykład:
for i in *; do mv "$i" "`echo $i | sed "s/regex/replace_text/"`"; done
Jeśli wyrażenie regularne zawiera grupy (np
\(subregex\
) wtedy można ich używać w tekście jako zastępczej\1\
,\2
itpźródło
Najłatwiej byłoby:
for i in F00001*; do mv "$i" "${i/F00001/F0001}"; done
lub przenośnie,
for i in F00001*; do mv "$i" "F0001${i#F00001}"; done
Spowoduje to zastąpienie
F00001
przedrostka w nazwach plików przezF0001
. kredyty dla mahesha tutaj: http://www.debian-administration.org/articles/150źródło
mv "$i" "${i/F00001/F0001}"
. Ale +1sed
komendaśrodki do wymiany:
z:
tak jak zwykłe
sed
polecenie. Jednak nawiasy&
i\n
znaczniki trochę to zmieniają.Ciąg wyszukiwania dopasowuje (i zapamiętuje jako wzorzec 1) pojedynczy znak na początku, po którym następuje pojedynczy znak, po którym następuje reszta ciągu (zapamiętywany jako wzorzec 2).
W łańcuchu zastępczym możesz odwołać się do tych dopasowanych wzorców, aby użyć ich jako części zamiany. Możesz również nazywać całą dopasowaną część jako
&
.Więc to
sed
polecenie tworzymv
polecenie na podstawie oryginalnego pliku (dla źródła) i znaków od 1 do 3, skutecznie usuwając znak 2 (dla miejsca docelowego). Wyświetli serię linii w następującym formacie:i tak dalej.
źródło
ls | sed "s/\(.\).\(.*\)/mv & \1\2/" | bash
ls
, przepuszczanie,sed
a następnie przepuszczanie przez powłokę jest niebezpieczne ! podlega wykonaniu dowolnego kodu ze sfałszowanymi nazwami plików. Problem polega na tym, że dane powinny być traktowane jako dane, a tutaj są one zwykle serializowane do kodu bez żadnych środków ostrożności. Chciałbym, żeby paxdiablo usunęło tę odpowiedź, ponieważ tak naprawdę nie pokazuje dobrych praktyk. (Natknąłem się na to pytanie, ponieważ początkujący losowo rurami| sh
po komendzie, że nie działa i po obejrzeniu tego pytania i odpowiedzi myślałem, że to działa lepiej Jestem przerażony!):)
.Odwrotny ukośnik-paren oznacza „dopasowując wzór, trzymaj się tego, co tutaj pasuje”. Później, po stronie tekstu zastępczego, możesz odzyskać te zapamiętane fragmenty za pomocą „\ 1” (pierwszy blok w nawiasach), „\ 2” (drugi blok) i tak dalej.
źródło
Jeśli wszystko, co naprawdę robisz, to usuwanie drugiej postaci, niezależnie od tego, co to jest, możesz to zrobić:
ale twoje polecenie buduje
mv
polecenie i przesyła je do powłoki w celu wykonania.To nie jest bardziej czytelne niż twoja wersja:
find -type f | sed -n 'h;s/.//4;x;s/^/mv /;G;s/\n/ /g;p' | sh
Czwarty znak jest usuwany, ponieważ
find
każda nazwa pliku jest poprzedzona znakiem „./”.źródło
| sh
po poleceniu, które nie działa, w nadziei, że zadziała lepszy. To przerażające! (a poza tym to nie jest dobra praktyka). Mam nadzieję, że zrozumiesz!Za pomocą zmiany nazwy perla ( musi mieć w przyborniku):
rename -n 's/0000/000/' F0000*
Usuń
-n
przełącznik, gdy wyjście wygląda dobrze, aby zmienić nazwę na rzeczywistość.Istnieją inne narzędzia o tej samej nazwie, które mogą, ale nie muszą być w stanie tego zrobić, więc bądź ostrożny.
Polecenie rename, które jest częścią
util-linux
pakietu, nie będzie.Jeśli uruchomisz następujące polecenie (
GNU
)i widzisz
perlexpr
, to wydaje się być właściwym narzędziem.Jeśli nie, aby uczynić go domyślnym (zwykle już tak jest)
Debian
i pochodną, taką jakUbuntu
:$ sudo apt install rename $ sudo update-alternatives --set rename /usr/bin/file-rename
Dla archlinux:
Dystrybucje z rodziny RedHat:
Pakiet „prename” znajduje się w repozytorium EPEL .
W przypadku Gentoo:
W przypadku * BSD:
lub
p5-File-Rename
Użytkownicy komputerów Mac:
Jeśli nie masz tego polecenia w innej dystrybucji, wyszukaj menedżera pakietów, aby go zainstalować lub zrób to ręcznie :
Starą samodzielną wersję można znaleźć tutaj
zmiana nazwy człowieka
To narzędzie zostało pierwotnie napisane przez Larry'ego Wall'a, ojca Perla.
źródło
Nawiasy wychwytują określone ciągi do użycia przez liczby z odwrotnym ukośnikiem.
źródło
ls F00001-0708-*|sed 's|^F0000\(.*\)|mv & F000\1|' | bash
źródło
Oto, co bym zrobił:
for file in *.[Jj][Pp][Gg] ;do echo mv -vi \"$file\" `jhead $file| grep Date| cut -b 16-| sed -e 's/:/-/g' -e 's/ /_/g' -e 's/$/.jpg/g'` ; done
Następnie, jeśli wygląda to dobrze, dodaj
| sh
na końcu. Więc:for file in *.[Jj][Pp][Gg] ;do echo mv -vi \"$file\" `jhead $file| grep Date| cut -b 16-| sed -e 's/:/-/g' -e 's/ /_/g' -e 's/$/.jpg/g'` ; done | sh
źródło
Kilka przykładów, które działają dla mnie:
$ tree -L 1 -F . . ├── A.Show.2020.1400MB.txt └── Some Show S01E01 the Loreming.txt 0 directories, 2 files ## remove "1400MB" (I: ignore case) ... $ for f in *; do mv 2>/dev/null -v "$f" "`echo $f | sed -r 's/.[0-9]{1,}mb//I'`"; done; renamed 'A.Show.2020.1400MB.txt' -> 'A.Show.2020.txt' ## change "S01E01 the" to "S01E01 The" ## \U& : change (here: regex-selected) text to uppercase; ## note also: no need here for `\1` in that regex expression $ for f in *; do mv 2>/dev/null "$f" "`echo $f | sed -r "s/([0-9] [a-z])/\U&/"`"; done $ tree -L 1 -F . . ├── A.Show.2020.txt └── Some Show S01E01 The Loreming.txt 0 directories, 2 files $
2>/dev/null
tłumi nieistotne dane wyjściowe (ostrzeżenia ...)odniesienie [ten wątek]: https://stackoverflow.com/a/2372808/1904943
zmiana przypadku: https://www.networkworld.com/article/3529409/converting-between-uppercase-and-lowercase-on-the-linux-command-line.html
źródło
for i in *; do mv $i $(echo $i|sed 's/AAA/BBB/'); done
źródło