확장자를 변경하기 위해 파일 이름을 바꾸고 싶습니다. 효과적으로 완료하려고 합니다.
mv *.txt *.tsv
하지만 이렇게 하면 다음과 같은 결과를 얻습니다.
*.tsv는 디렉터리가 아닙니다.
mv
처음 10번의 Google 클릭 표시가 이와 같이 작동한다는 것이 조금 이상하다고 생각합니다 .
답변1
이것이 귀하의 질문에 대한 답변이 아니라는 것을 알고 있지만 해결 방법 루프가 아닌 파일 이름을 바꾸는 다른 방법을 찾고 있다면 find
? 나는 수십만 개의 파일이 포함된 대규모 디렉터리의 파일 확장자를 바꾸기 위해 이 명령을 여러 번 사용했습니다. 이는 모든 POSIX 호환 시스템에서 작동합니다.
find . -name "*.gappedPeak" -exec sh -c 'mv "$1" "${1%.gappedPeak}.bed"' _ {} \;
명령 분석:
'
.
' => '로 표시된 현재 디렉터리부터 시작하는 검색 경로입니다. '
-name
=> 조회 일치 이름 설정(이 경우 로 끝나는 모든 파일.gappedPeak
)
-exec
=> 각 게임에서 다음 명령을 실행하십시오.
sh -c
=> 'exec'는 각 게임마다 별도의 쉘 환경을 생성합니다.
mv "$1" "${1%.gappedPeak}.bed"
=>mv
첫 번째 변수(다음과 같이 표현됨)1)(현재 파일 이름)이 새 이름으로 변경됩니다. 여기서는 하위 문자열 일치를 수행하고 제거하므로 첫 번째 var를 다시 가져옵니다.1문자열에서 제거하는 데 사용됩니다%
..gappedPeak
마지막.bed
변수는 나머지 변수(아래 예에서는 , )를 연결하여 새 파일 이름을 만듭니다.testNumber
.bed
testNumber.bed
밑줄은 자리 표시자입니다.$0
{}
는 명령으로 찾은*.gappedPeak
각 ( ) 파일 이름으로 대체find
되며 다음과 같습니다.1sh
명령 에 .
\;
명령의 끝을 표시합니다-exec
.';'
또는 을 사용할 수도 있습니다";"
.
예:
[user@before]# ls -lh
total 0
-rw-r--r--. 1 root root 0 Jan 26 11:40 test1.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test2.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test3.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test4.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test5.gappedPeak
[user@after]# ls -lh
total 0
-rw-r--r--. 1 root root 0 Jan 26 11:40 test1.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test2.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test3.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test4.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test5.bed
답변2
이 답변은 확장을 변경하는 데 도움이 되지 않지만 명령이 예상한 대로 수행되지 않는 이유를 이해하는 데 도움이 됩니다.
명령을 실행하면 다음이 수행됩니다.
mv *.txt *.tsv
쉘, bash를 가정해보자.확장하다와일드카드만약에일치하는 파일(디렉터리 포함)이 있습니다. 파일 목록은 여기에서 프로그램으로 전달됩니다 mv
. 일치하는 항목이 없으면 확장되지 않은 버전이 전달됩니다.
다시:껍데기프로그램이 아닌 확장 모드입니다.
많은 예가 아마도 이것이 작동하지 않는 이유를 이해하는 가장 좋은 방법일 것입니다. 그럼 시작해 보겠습니다.
예시 1:
$ ls
file1.txt file2.txt
$ mv *.txt *.tsv
mv
지금 온라인에서 벌어지고 있는 일은껍데기*.txt
일치하는 파일로 확장합니다 . 변경되지 않은 파일이 없기 때문입니다 *.tsv
.
명령 mv
이 호출됩니다.두 가지 특수 매개변수가 있습니다.:
argc
: 프로그램을 포함한 매개변수의 수입니다.argv
: 프로그램을 첫 번째 항목으로 포함하는 인수 배열입니다.
위의 예에서는 다음과 같습니다.
argc = 4
argv[0] = mv
argv[1] = file1.txt
argv[2] = file2.txt
argv[3] = *.tsv
프로그램 mv
은 마지막 인수가 *.tsv
디렉터리인지 확인합니다. 그렇지 않으면 파일 연결용으로 설계되지 않았기 때문에 프로그램을 계속할 수 없습니다. (모든 파일을 하나로 결합합니다.) 또한 임의로 디렉토리를 만들 수 없습니다.
결과적으로 오류가 중단되고 보고됩니다.
mv: target ‘*.tsv’ is not a directory
예 2:
이제 다음과 같이 말하면:
$ mv *1.txt *.tsv
명령 mv
은 다음과 같이 실행됩니다.
argc = 3
argv[0] = mv
argv[1] = file1.txt
argv[2] = *.tsv
이제 존재 mv
하는지 다시 확인하십시오 *.tsv
. 아무것도 없었기 때문에 파일은 .ie file1.txt
로 이동되었습니다 *.tsv
. 파일 이름은 *.tsv
별표와 모두로 변경되었습니다.
$ mv *1.txt *.tsv
‘file1.txt’ -> ‘*.tsv’
$ ls
file2.txt *.tsv
예시 3:
대신 다음과 같이 말했다면:
$ mkdir *.tsv
$ mv *.txt *.tsv
명령 mv
은 다음과 같이 실행됩니다.
argc = 3
argv[0] = mv
argv[1] = file1.txt
argv[1] = file2.txt
argv[2] = *.tsv
*.tsv
이제 디렉터리이므로 파일은 결국 해당 디렉터리로 이동됩니다 .
이제: 인텐트가 실제로 와일드카드를 유지하는 경우와 같은 명령을 사용하면 some_command *.tsv
항상 인용되어야 합니다. 따옴표를 사용하면 일치하는 항목이 있는 경우 와일드카드가 확장되는 것을 방지할 수 있습니다. 예를 들어 mkdir "*.tsv"
.
예시 4:
이렇게 하면 다음과 같은 확장을 더 자세히 볼 수 있습니다.
$ ls
file1.txt file2.txt
$ mkdir *.txt
mkdir: cannot create directory ‘file1.txt’: File exists
mkdir: cannot create directory ‘file2.txt’: File exists
예시 5:
이제 이 mv
명령은 여러 파일에서 작동할 수 있고 작동합니다. 하지만 2개 이상이면 마지막 디렉터리가 대상 디렉터리여야 합니다. ( -t TARGET_DIR
적어도 GNU mv에서는 이 옵션을 사용하도록 선택할 수 있습니다 .)
그래서 이것은 괜찮습니다:
$ ls -F
b1.tsv b2.tsv f1.txt f2.txt f3.txt foo/
$ mv *.txt *.tsv foo
이는 다음 mv
과 같이 호출됩니다.
argc = 7
argv[0] = mv
argv[1] = b1.tsv
argv[2] = b2.tsv
argv[3] = f1.txt
argv[4] = f2.txt
argv[5] = f3.txt
argv[6] = foo
모든 파일은 디렉토리에 저장됩니다 foo
.
귀하의 링크는. 귀하는 mv
전혀 언급되지 않은 하나를 (댓글에) 제공했습니다 rename
. 그러나 귀하의 주장을 표현하는 공유할 수 있는 링크나 매뉴얼 페이지가 더 있습니까?
답변3
mv *.txt *.tsv
작동하지 않습니다. mv
한 번에 하나의 파일만 이름을 바꿀 수 있습니다. 당신은 이러한 설명을 오해했거나 틀렸습니다.
mmv
한 번에 여러 파일의 이름을 바꿀 수 있습니다 rename
. 그러나 around rename
에는 서로 다른 방식으로 호출되는 두 가지 버전이 있습니다 . 여기에 대해 많은 질문이 있어야합니다.
답변4
예를 들어, 명령을 실행할 때 디렉토리에 및 파일이 있는 경우 asd.txt
두 파일을 이름이 지정된 디렉토리로 이동하려고 시도합니다. 해당 디렉터리가 없기 때문에 오류가 보고됩니다.qwe.txt
mv *.txt *.tsv
*.tsv