Przepraszam, jeśli ma to gdzie indziej odpowiedź, nie mam pojęcia, jak wyszukać mój problem.
Uruchomiłem kilka symulacji na serwerze redhat Linux HPC, a mój kod do obsługi struktury folderów w celu zapisania danych wyjściowych miał niefortunny błąd. Mój kod Matlab do utworzenia folderu to:
folder = [sp.saveLocation, 'run_', sp.run_number, '/'];
gdzie sp.run_number
była liczba całkowita. Zapomniałem przekonwertować go na ciąg, ale z jakiegoś powodu uruchomienie mkdir(folder);
(w Matlabie) nadal się powiodło. W rzeczywistości symulacje przebiegły bez żadnych problemów, a dane zostały zapisane w odpowiednim katalogu.
Teraz, gdy struktura folderów jest sprawdzana / drukowana, otrzymuję następujące sytuacje:
- Kiedy próbuję uzupełnić kartę autouzupełnianiem:
run_ run_^A/ run_^B/ run_^C/ run_^D/ run_^E/ run_^F/ run_^G/ run_^H/ run_^I/
- Kiedy używać
ls
:run_ run_? run_? run_? run_? run_? run_? run_? run_? run_? run_?
. - Kiedy przesyłam do mojego komputera Mac przy użyciu rsync,
--progress
opcja pokazuje:run_\#003/
itd. Z (zakładam) liczbą pasującą do liczby całkowitej wsp.run_number
dopełnieniu do trzech cyfr, więc 10. przebieg jestrun_\#010/
- Kiedy przeglądam foldery w wyszukiwarce, widzę
run_ run_ run_ run_ run_ run_ run_ run_ run_ run_?
- Patrząc na to pytanie i używając polecenia
ls | LC_ALL=C sed -n l
otrzymuję:
run_$
run_\001$
run_\002$
run_\003$
run_\004$
run_\005$
run_\006$
run_\a$
run_\b$
run_\t$
run_$
Nie mogę zarządzać cd
folderami przy użyciu tych reprezentacji.
Mam tysiące tych folderów, więc muszę to naprawić za pomocą skryptu. Która z tych opcji jest poprawną reprezentacją folderu? Jak mogę programowo odwoływać się do tych folderów, aby zmienić ich nazwę na poprawnie sformatowaną nazwę za pomocą skryptu bash? I chyba ze względu na ciekawość, jak do diabła to się stało?
źródło
^A
jest też dosłownie^
po nimA
, ale Ctrl-A (możesz wpisać go za pomocą Ctrl-V Ctrl-A, ponieważ Ctrl-A jest ogólnie skrótem do powłoki).run_
i muszę coś/
. Każdy inny znak jest prawidłowy, w tym znaki kontrolne. Nie wiem, co zrobiłby Matlab, gdyby sp.run_number miał wartość 0 (prawdopodobnie przerwałby z błędem lub produkowałrun_
, ponieważ bajt NUL zakończyłby ciąg nazwy katalogu). Oczywiście byłoby to również problematyczne dla 16-bitowych (lub wyższych) wartości, które zawierały bajt NUL, a także zmieniałoby się w zależności od endianowości systemu z uruchomionym matlabem.Odpowiedzi:
Możesz użyć perla
rename
narzędzia (akaprename
lubfile-rename
), aby zmienić nazwę katalogów.UWAGA: Nie należy tego mylić
rename
odutil-linux
, lub jakakolwiek inna wersja.To używa Perla
ord()
funkcji do zastąpienia każdego znaku kontrolnego w nazwie pliku numerem porządkowym tego znaku. np.^A
staje się 1,^B
staje się 2 itd.-n
Opcja jest na sucho, aby pokazać, corename
byłoby zrobić jeśli go. Usuń go (lub zamień-v
na pełne dane wyjściowe), aby faktycznie zmienić nazwę.The
e
Modyfikator ws/LHS/RHS/eg
przyczyn operacyjnych perl wykonać RHS (zastąpienie) jako kod Perl, i$1
jest dopasowane dane (znak kontrolny) od LHS.Jeśli chcesz, by w nazwach plików występowały liczby uzupełnione zerami, możesz połączyć je
ord()
zsprintf()
. na przykładPowyższe przykłady działają wtedy i tylko wtedy, gdy
sp.run_number
w skrypcie Matlab był w zakresie 0..26 (więc tworzył znaki kontrolne w nazwach katalogów).Aby poradzić sobie z KAŻDYM znakiem 1-bajtowym (tj. Od 0..255), użyjesz:
Jeśli
sp.run_number
może być> 255, musisz użyć Perlaunpack()
funkcji zamiastord()
. Nie wiem dokładnie, jak Matlab wyprowadza nieprzekształcone int w ciągu, więc będziesz musiał eksperymentować. Zobaczperldoc -f unpack
szczegóły.np. następujące polecenie rozpakuje zarówno 8-bitowe, jak i 16-bitowe wartości bez znaku i wstawi je zerowo do szerokości 5 cyfr:
źródło
-n
opcją, ale to mówi mi, że jest to nieprawidłowa opcja - informacje o wersji dają mi,rename from util-linux 2.23.2
więc nie jestem pewien, czy to ta sama funkcjarename
narzędzia.util-linux
jestrename
to bardzo różne, mniej zdolny, a możliwych opcji są niekompatybilne. jeśli korzystasz z Debiana lub podobnego, spróbuj zainstalowaćfile-rename
pakiet. w przeciwnym razie zainstaluj odpowiedni pakiet dla swojej dystrybucji. może być już zainstalowany, spróbuj uruchomićprename
lubfile-rename
zamiast po prosturename
.Wygląda więc na to, że
mkdir([...])
w Matlab łączy elementy tablicy, aby zbudować nazwę pliku jako ciąg. Ale zamiast tego podałeś jej liczbę, a liczby są takimi, jakimi naprawdę są znaki na komputerze. Kiedysp.run_number
był1
, dał ci znak z wartością1
, a następnie znak z wartością2
itp.Są to znaki kontrolne, nie mają symboli do wydrukowania, a wydrukowanie ich na terminalu miałoby inne konsekwencje. Zamiast tego często są reprezentowane przez różne rodzaje ucieczek:
\001
(ósemkowe),\x01
(szesnastkowe),^A
znaków wszystkie są typowymi reprezentacjami dla postaci o wartości1
. Znak o wartości zero jest nieco inny, to bajt NUL, który służy do oznaczania końca łańcucha w C i w wywołaniach systemowych Unix.Jeśli przekroczysz 31, zaczniesz widzieć znaki do wydrukowania, 32 to spacja (choć mało widoczna), 33 =
!
, 34 ="
itd.Więc,
run_ run_^A/ run_^B/
- Pierwszyrun_
odpowiada bajtowi zero, łańcuch kończy się tam. Inne pokazują, że twoja powłoka lubi używać wyświetlania kodów kontrolnych^A
. Notacja wskazuje również na to, że znak o wartości liczbowej 1 można wprowadzić jako Ctrl-A, chociaż powinieneś powiedzieć powłoce, aby interpretowała nie jako znak kontrolny, ale jako literał, Ctrl-V Ctrl-Apowinna to zrobić przynajmniej w Bash.ls:
run_ run_? run_?
-ls
nie lubi drukować znaków niedrukowalnych na terminalu, zastępuje je znakami zapytania.rsync:
run_\#003/
- ten jest dla mnie nowy, ale idea jest taka sama, odwrotny ukośnik oznacza ucieczkę, a reszta to wartość liczbowa znaku. Wydaje mi się, że liczba tutaj jest ósemkowa, jak w bardziej powszechnej\003
.za pomocą polecenia
ls | LC_ALL=C sed -n l
...run_\006$
run_\a$
run_\b$
run_\t$
-\a
,\b
i\t
atom C uchodzi alarmu (dzwon) backspace i zakładki, odpowiednio. Mają wartości liczbowe 7, 8 i 9, więc powinno być jasne, dlaczego po nich\006
. Użycie tych znaków C jest kolejnym sposobem na oznaczenie znaków kontrolnych. Końcowe znaki dolara oznaczają koniec linii.Co do tego
cd
, zakładając, że moje założenia są słuszne,cd run_
powinien przejść do tego jednego katalogu bez nieparzystych znaków końcowych icd run_?
powinien dać błąd, ponieważ znak zapytania jest znakiem globalnym, który pasuje do dowolnego pojedynczego znaku, i istnieje wiele pasujących nazw plików, alecd
tylko oczekuje jednego.Wszystkie w pewnym sensie ...
W bashu można użyć
\000
i\x00
ucieczek wewnątrz$'...'
cudzysłowów do reprezentowania znaków specjalnych, więc$'run_\033
(ósemkowe) lub$'run_\x1b'
odpowiadać katalogu o wartości 27 znaków (co zdarza się ESC). (Nie sądzę, że Bash obsługuje znaki ucieczki z liczbami dziesiętnymi).Odpowiedź cas ma skrypt do zmiany nazwy, więc nie pójdę tam.
źródło
ls
, istnieje kilka opcji cytowania, w tym-b
/--escape
i--quoting-style=
, lubQUOTING_STYLE
zmienna środowiskowa, które kontrolują sposób wyświetlania znaków niedrukowalnych. Nie sądzę jednak, aby istniała opcja, aby wolała ósemkowe ucieczki od wersji postaci.Najłatwiej byłoby utworzyć niewłaściwą nazwę pliku i poprawną nazwę pliku w tym samym środowisku, w którym doszło do nieszczęścia, a następnie po prostu przenieść / zmienić nazwę folderów na prawidłowe nazwy.
Aby uniknąć kolizji między istniejącymi nazwami, lepiej użyj innego folderu docelowego.
Jeśli to możliwe, wolałbym naprawić skrypt i po prostu uruchomić go ponownie; naprawienie dziwnych sekcji zwłok prawdopodobnie kosztuje więcej i może wprowadzić nowe problemy.
Powodzenia!
źródło