Próbuję usunąć rozszerzenie nazwy pliku z listy plików, które wygenerowałem za pomocą następującego skrypt bash:
#!/bin/bash file_list=$(find . -type f) #assuming that the files are stored in the same directory trimmed_file_list=$(printf "%s\n" "${file_list[@]%.*}") printf "%s\n" "${trimmed_file_list[@]}"
To rozszerzenie odcina rozszerzenie z ostatniego wpisu na liście, ale nie żadnego z wcześniejszych.
Na przykład chcę mieć następującą listę:
file1.pdf file2.pdf file3.png
Aby zostać
file1 file2 file3
Ale zamiast tego otrzymuję:
file1.pdf file2.pdf file3
Wolałbym nie robić tego w pętli, chciałbym używać rozwijania parametrów. Chcę uniknąć cięcia, ponieważ chcę usunąć tylko ostatnie rozszerzenie w pliku.
Jest wiele tematów dotyczących rozszerzania parametrów i wygląda na to, że bash może się dusić na find
” użycie nowych linii … Naprawdę nie jestem pewien. Jeśli inny z istniejących wcześniej tematów wyjaśnia ten problem, nie rozumiem w pełni, co się dzieje.
Tematy, które się pojawiają powiązane, ale nie wydają się rozwiązywać mojego problemu:
- Jak mogę usunąć rozszerzenie nazwy pliku w skrypcie powłoki?
- Rozwijanie parametrów powłoki w tablicach
- Porzucanie nazwy pliku rozszerzenia z find -exec
Komentarze
- Twój tytuł wspomina o tablicach, ale w kodzie nie ma tablicy.
- @Kusalananda Dziękuję! ' zdałem sobie z tego sprawę, odkąd o to zapytałem. Wciąż się uczę 🙂
- @Kusalananda ' poszedłem dalej i zmodyfikowałem pytanie, aby dokładniej odpowiadało problemowi. Powinno to zapobiec trafianiu na stronę przez błędne wyszukiwania Google. Dziękuję za informację!
Odpowiedź
Wszystko można było zrobić jednym poleceniem.
find /path/to -type f -execdir bash -c "printf "%s\n" "${@%.*}"" bash {} +
Komentarze
- Dziękuję! Właściwie muszę utworzyć kilka kopii tablicy, jedną dla menu ze zmodyfikowaną nazwą pliku i taką, która zachowa pierwotną wartość indeksu, aby móc wywołać plik z menu. To naprawdę niesamowite, ile bash może zdziałać! Możliwość osadzenia wszystkiego w jednym poleceniu wciąż mnie powala! : D
Odpowiedź
Uważam, że wolałbyś utworzyć tablicę zamiast ciągu:
IFS=$"\n" # split on newline only set -o noglob # disable the glob part file_list=($(find . -name "*.*" -type f))
Lub z bash 4.4+, bez przerywania ścieżek plików ze znakami nowej linii:
readarray -td "" file_list < <(find . -name "*.*" -type f -print0)
Wtedy rozwinięcie parametrów powinno zadziałać, chociaż w tym przypadku bardziej sensowne byłoby ponowne użycie zmiennej tablicowej:
trimmed_file_list=("${file_list[@]%.*}")
W przykładowym kodzie tworzysz ciąg następnie prosząc rozwinięcie parametrów o usunięcie wszystkiego po ostatnim znaku kropki w pełnym ciągu.
Komentarze
- Dziękuję! Przetestuję to, gdy tylko dotrę rano do biurka.
- Zakłada się, że żadne nazwy plików w tym katalogu nie zawierają białych znaków ani znaków globalnych.
- @Wildcard powinno być rozwiązane w najnowszej edycji.
- @Wildcard Dzięki za wskaźnik! Ja ' m generuję pliki, które są wrzucane do tego katalogu programowo, więc nie powinno to ' być problemem.
Odpowiedź
Twój kod nie zawiera żadnych tablic. Ponadto umieszcza listę nazw plików w łańcuchu $file_list
. Treść ciągu kończy się na file3.png
, a podstawienie parametru usuwa .png
z ciągu, pozostawiając pojedynczy ciąg nazw plików, gdzie ostatnia nazwa pliku nie ma sufiksu nazwy pliku.
Umieszczenie wielu oddzielnych obiektów (nazw ścieżek) w jednym ciągu automatycznie dyskwalifikuje skrypt z poprawnego działania dla plików, których nazwy zawierają spacje (lub jakikolwiek separator użyty w ciągu). Używanie tablicy nie pomogłoby, ponieważ nadal dzieliłbyś wynik find
na białe znaki.
Aby przyciąć rozszerzenie ze wszystkich nazw plików zwykłych plików w bieżącym katalogu lub poniżej:
find . -type f -name "*.*" -exec sh -c " for pathname do printf "Would move %s to %s...\n" "$pathname" "${pathname%.*}" # mv -i "$pathname" "${pathname%.*}" done" sh {} +
Szuka zwykłych plików, których nazwa zawiera co najmniej jedną kropkę. Ścieżki do tych plików są wprowadzane partiami do małego skryptu powłoki, który przetwarza je w pętli. Skrypt powłoki zmienia nazwy plików, usuwając ostatnią kropkę w nazwie pliku i wszystko, co nastąpi później. Faktyczne polecenie mv
jest dla bezpieczeństwa zakomentowane.
Polecenie find
działa jako generator nazw ścieżek dla wewnętrzny skrypt powłoki i gwarantujemy prawidłowe przetwarzanie ścieżek zawierających spacje, znaki nowej linii i tabulatory. Nie ma potrzeby przechowywania wyników poleceń w zmiennych.
Jeśli masz tablicę nazw ścieżek, prawdopodobnie utworzoną za pomocą
shopt -s globstar nullglob file_list=( **/*.* ) # get pathnames of files with dots in their names
Wtedy możesz wypisać nazwy ścieżek bez sufiksów z
printf "%s\n" "${file_list[@]%.*}"
Czy to ci pomogło, nie wiem. Jeśli chcesz użyć nazw ścieżek bez sufiksów do czegoś , wówczas użycie wyniku powyższego polecenia printf
byłoby niewłaściwym rozwiązaniem (nie musiałbyś ponownie zajmować się dziwną nazwą ścieżki). a sposób usunięcia sufiksów nazw plików zależy od tego, co chciałbyś zrobić z wynikiem.
Powiązane:
Komentarze
- Dziękuję! Twoje opanowanie bash jest bardzo oczywiste! ' nadal skrobię powierzchnię … Dziękuję za poświęcenie czasu na pomoc 🙂