죄송합니다. 다른 곳에 답변이 있는 경우 내 질문을 어떻게 검색해야 할지 모르겠습니다.
Redhat Linux HPC 서버에서 일부 시뮬레이션을 실행하고 있는데 출력을 저장하기 위해 폴더 구조를 처리하는 코드에 불행한 버그가 있습니다. 폴더를 만드는 내 MATLAB 코드는 다음과 같습니다.
folder = [sp.saveLocation, 'run_', sp.run_number, '/'];
sp.run_number
정수는 어디에 있습니까? 문자열로 변환하는 것을 잊었지만 어떤 이유로 mkdir(folder);
matlab에서 실행하면 여전히 성공합니다. 실제로 시뮬레이션은 원활하게 실행되며 데이터는 일치하는 디렉터리에 저장됩니다.
이제 폴더 구조를 쿼리/인쇄할 때 다음을 얻습니다.
- 탭 자동 완성을 사용하려고 하면:
run_ run_^A/ run_^B/ run_^C/ run_^D/ run_^E/ run_^F/ run_^G/ run_^H/ run_^I/
- 내가 사용할 때
ls
:run_ run_? run_? run_? run_? run_? run_? run_? run_? run_? run_?
- rsync를 사용하여 Mac으로 전송할 때
--progress
옵션에는 다음과 같이 표시됩니다.run_\#003/
(내 가정에서는) 세 자리 숫자로 패딩된 정수와 일치하는 숫자sp.run_number
이므로 10번째 실행은 다음과 같습니다.run_\#010/
- Finder에서 폴더를 보면
run_ run_ run_ run_ run_ run_ run_ run_ run_ run_?
- 보고 있다이것질문을 받고 내가 얻은 명령을 사용하여
ls | LC_ALL=C sed -n l
:
run_$
run_\001$
run_\002$
run_\003$
run_\004$
run_\005$
run_\006$
run_\a$
run_\b$
run_\t$
run_$
cd
이러한 표현을 사용하면 폴더에 들어갈 수 없습니다 .
이와 같은 폴더가 수천 개 있으므로 이 문제를 해결하려면 스크립트가 필요합니다. 다음 옵션 중 폴더를 올바르게 표현한 것은 무엇입니까? bash 스크립트를 사용하여 올바른 형식의 이름으로 이름을 바꿀 수 있도록 프로그래밍 방식으로 이러한 폴더를 참조하려면 어떻게 해야 합니까? 궁금해서 그러는 것 같은데, 대체 어떻게 이런 일이 일어난 걸까요?
답변1
Perl 유틸리티( 또는 rename
라고도 함 )를 사용하여 디렉토리 이름을 바꿀 수 있습니다.prename
file-rename
노트:또는 다른 버전 rename
과 혼동하지 마십시오 .util-linux
rename -n 's/([[:cntrl:]])/ord($1)/eg' run_*/
이는 Perl의 ord()
기능을 사용하여 파일 이름의 각 제어 문자를 해당 문자의 서수로 대체합니다. 예를 들어 ^A
1이 되고 ^B
2가 됩니다.
이 -n
옵션은 콘텐츠를 표시하기 위한 시험 실행에 사용됩니다.rename
회의허락하신다면 그렇게 하세요. 실제로 이름을 바꾸려면 이를 제거하거나 -v
자세한 출력으로 대체하십시오.
e
연산의 수정자는 s/LHS/RHS/eg
perl이 RHS(대체)를 Perl 코드로 수행하도록 하며 $1
LHS의 일치하는 데이터(제어 문자)입니다.
파일 이름에 0으로 채워진 숫자를 사용하려면 예를 ord()
들어 sprintf()
.
$ rename -n 's/([[:cntrl:]])/sprintf("%02i",ord($1))/eg' run_*/ | sed -n l
rename(run_\001, run_01)$
rename(run_\002, run_02)$
rename(run_\003, run_03)$
rename(run_\004, run_04)$
rename(run_\005, run_05)$
rename(run_\006, run_06)$
rename(run_\a, run_07)$
rename(run_\b, run_08)$
rename(run_\t, run_09)$
위의 예는 작동합니다만약에 그리고 만약에 sp.run_number
matlab 스크립트에서 해당 범위는 0..26입니다(따라서 디렉터리 이름에 제어 문자를 생성합니다).
1바이트 문자(예: 0..255부터 시작)를 처리하려면 다음을 사용할 수 있습니다.
rename -n 's/run_(.)/sprintf("run_%03i",ord($1))/e' run_*/
255 이상이 가능 하다면 대신 sp.run_number
Perl의 함수를 사용해야 합니다 . matlab이 변환되지 않은 int를 문자열로 출력하는 방법을 모르므로 실험해야 합니다. 자세히보다.unpack()
ord()
perldoc -f unpack
예를 들어, 다음 코드는 8비트 및 16비트 부호 없는 값의 압축을 풀고 5비트 너비로 제로 패딩합니다.
rename -n 's/run_(.*)/sprintf("run_%05i",unpack("SC",$1))/e' run_*/
답변2
궁금해서 그러는 것 같은데, 대체 어떻게 이런 일이 일어난 걸까요?
folder = [sp.saveLocation, 'run_', sp.run_number, '/'];
sp.run_number
정수는 어디에 있습니까? 문자열로 변환하는 것을 잊었지만 어떤 이유로 실행 중입니다mkdir(folder)
. (matlab에서) 여전히 성공합니다.
mkdir([...])
따라서 Matlab에서는 배열의 멤버가 연결되어 파일 이름을 문자열로 만드는 것 같습니다 . 그러나 당신은 그것에 숫자를 부여했고 숫자는 컴퓨터의 실제 문자입니다. 따라서 sp.run_number
was 에서는 1
value 역할을 제공한 1
다음 value 역할 2
등을 제공합니다.
이는 제어 문자이며 인쇄 가능한 기호가 없으며 터미널에 인쇄하면 다른 결과가 발생합니다. 따라서 일반적으로 다양한 유형의 이스케이프 문자로 표시됩니다. ( \001
8진수), \x01
(16진수)는 ^A
모두 값이 있는 문자의 일반적인 표현입니다 1
. 0 값 문자는 약간 다릅니다. C 및 Unix 시스템 호출에서 문자열 끝을 표시하는 데 사용되는 NUL 바이트입니다.
31 이상으로 올라가면 인쇄 가능한 문자가 보이기 시작합니다. 32는 공백(덜 명확하지만), 33 = !
, 34 = "
등입니다.
그래서,
run_ run_^A/ run_^B/
— 첫 번째run_
바이트는 문자열이 끝나는 0바이트에 해당합니다. 다른 것들은 쉘이 디스플레이 제어 코드 사용을 선호한다는 것을 나타냅니다^A
. 이 표기법은 또한 값이 1인 char을 로 입력할 수 있다는 사실을 암시합니다 . 하지만 적어도 Bash에서는 Ctrl-A이를 제어 문자로 해석하지 않고 리터럴로 해석하도록 쉘에 지시해야 합니다 .Ctrl-V Ctrl-Als:
run_ run_? run_?
—ls
인쇄할 수 없는 문자를 터미널에 인쇄하는 것을 좋아하지 않으며 이를 물음표로 바꿉니다.rsync:
run_\#003/
— 이것은 나에게 새로운 것이지만 아이디어는 동일합니다. 백슬래시는 이스케이프를 표시하고 나머지는 문자의 숫자 값입니다. 제가 보기엔 여기에 있는 숫자가 더 일반적인 숫자처럼 8진수로 되어 있는 것 같습니다\003
.ls | LC_ALL=C sed -n l
...run_\006$
run_\a$
run_\b$
run_\t$
— 명령을 사용 하고 는\a
각각 경고(링), 백스페이스 및 탭에 대한 C 이스케이프 문자입니다. 그들의 수치는 7, 8, 9이므로 왜 맨 뒤에 있는지가 분명할 것이다 . 이러한 C 이스케이프를 사용하는 것은 제어 문자를 표시하는 또 다른 방법입니다. 뒤에 오는 달러 기호는 줄의 끝을 표시합니다.\b
\t
\006
의 경우 cd
내 가정이 정확하다고 가정하면 cd run_
이상한 후행 문자가 없는 단일 디렉터리로 이동해야 하며 cd run_?
물음표는 단일 문자와 일치하는 전역 문자이고 일치하는 파일 이름이 여러 개 있기 때문에 오류가 발생해야 합니다. cd
하나만 기대하세요.
다음 옵션 중 폴더를 올바르게 표현한 것은 무엇입니까?
이 모든 것은 어떤 의미에서는...
Bash에서 \000
특수 문자는 따옴표 안의 및 이스케이프 문자(8진수) 또는 문자 값 27(ESC임)에 해당하는 디렉터리를 사용하여 표현할 수 있습니다. (Bash는 십진수 이스케이프를 지원하지 않는 것 같습니다.)\x00
$'...'
$'run_\033
$'run_\x1b'
cas의 답변에는 이름을 바꾸는 스크립트가 있으므로 거기에는 가지 않겠습니다.
답변3
가장 쉬운 방법은 사고가 발생한 동일한 환경에서 잘못된 파일명과 올바른 파일명을 생성한 후 폴더를 올바른 이름으로 이동/변경하는 것입니다.
기존 이름 간의 충돌을 피하려면 다른 대상 폴더를 사용하는 것이 가장 좋습니다.
./saveLocationA/wrongname1 -> ./saveLocationB/correctname1
./saveLocationA/wrongname2 -> ./saveLocationB/correctname2
./saveLocationA/wrongname3 -> ./saveLocationB/correctname3
가능하다면 스크립트를 수정하고 다시 실행하고 싶습니다. 나중에 이상한 오류를 수정하면 더 많은 비용이 들고 새로운 문제가 발생할 수 있습니다.
행운을 빌어요!