확장자를 변경하려면 mv로 여러 파일 이름 바꾸기


27

파일 이름을 변경하여 확장명을 변경하고 효과적으로 달성하려고합니다.

mv *.txt *.tsv

그러나 이것을 할 때 나는 얻는다 :

* .tsv는 디렉토리가 아닙니다

처음 10 개의 Google 히트 쇼 mv가 이와 같이 작동 한다는 것이 다소 이상하다고 생각합니다.


해당 파일의 이름을 정확하게 바꾸는 방법 을 설명해야 합니다.
Totor

1
글쎄, 확장자가 * .gappedPeak 인 파일이 있고 이름을 * .bed로 바꾸고 싶습니다. 그들은 모두 같은 디렉토리에 있습니다. 매우 단순해야하지만 성공하기 위해서는 전체 for 루프가 필요했습니다
Sander Van der Zeeuw

Google에서 찾은 내용은 MSDOS에 적용됩니다.
tiktak

@devnull의 대체 솔루션이 정말 유용합니다
lucasvw

답변:


22

명령을 실행할 때 :

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. 파일 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명령이 여러 파일에서 작동 할 수 있습니다. 그러나 둘 이상이 있으면 마지막 디렉토리가 대상 디렉토리 여야합니다. (선택적 -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. 더 많은 링크가 있으면 공유 할 수 있습니다. 이것을 주장하는 매뉴얼 페이지뿐만 아니라 표현됩니다.


30

나는 이것이 당신의 질문에 대답하지 않는다는 것을 알고 있지만, 당신이 당신의 해결책 루프와 비교하여 파일의 이름을 바꾸는 다른 방법을 찾고 find있다면 왜 사용하지 않습니까? 이 명령을 여러 번 사용하여 큰 디렉토리의 파일 확장자를 수십만 개의 파일로 대체했습니다. 이것은 POSIX 호환 시스템에서 작동해야합니다.

find . -name "*.gappedPeak" -exec sh -c 'mv "$1" "${1%.gappedPeak}.bed"' _ {} \;

명령 분석 :

  1. ' .'=> '로 표시된 현재 디렉토리에서 시작하는 검색 경로. '

  2. -name=> 찾기 일치 이름 설정 (이 경우으로 끝나는 모든 파일 .gappedPeak)

  3. -exec => 일치 할 때마다 다음 명령을 실행하십시오.

  4. sh -c => 'exec'는 각 일치에 대해 독립적 인 셸 환경을 만듭니다.

  5. mv "$1" "${1%.gappedPeak}.bed"=> 현재 파일 이름 인 mv첫 번째 변수 ( $ 1 로 표시 )는 새 이름입니다. 여기에 하위 문자열 일치 및 삭제를 수행합니다. 첫 번째 var, $ 1을 다시 사용 하여 문자열에서 %삭제 .gappedPeak하십시오. .bed말은 바로 지금 남아있는 변수 연결해 으로, 새로운 생성, 파일 이름을.test#.bedtest#.bed

  6. 밑줄은 $ 0 의 자리 표시 자입니다.

  7. 이 명령으로 찾은 {}각 ( *.gappedPeak) 파일 이름으로 바뀌고 find명령의 $ 1이 됩니다 sh.

  8. \;-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

각 부분의 기능을 설명하는 명령을 진행할 수 있습니까?
user1717828

죄송합니다. 게시물을 업데이트했습니다. 희망이 도움이됩니다.
devnull

1
정말 고마워요! A를 bash는 가이드 와 설명 나는 모든 것을 얻을 수 있었다.
user1717828

문제 없어. 도움이되어 기쁘다.
devnull

매력처럼 작동합니다. 다음 은 여러 하위 디렉토리에서 file.abc-> blub.xyz에 대한 또 다른 단순화 된 예입니다 .find . -name "file.abc" -exec sh -c 'mv "$1" "$(dirname $1)/blub.xyz"' _ {} \;
Mahn

9

mv *.txt *.tsv작동하지 않습니다. mv한 번에 하나의 파일 이름 만 바꿀 수 있습니다. 설명을 잘못 이해했거나 잘못되었습니다.

mmv그리고 rename한 번에 여러 파일 이름을 바꿀 수 있습니다. 그러나 두 가지 버전이 rename있습니다. 여기에 대해 많은 질문이 있어야합니다.


1
cyberciti.biz/tips/... 구글의 첫 번째 히트 내가 그렇게 이상한 발견 왜 MV 잘 먹으 렴으로 일해야한다고 말하고있다
샌더 밴 제우 데르

3
@SanderVanderZeeuw 나는 당신이 무엇을 읽었는지 모른다. 예제는 rename아닌을 사용 mv합니다.
Hauke ​​Laging

1
죄송합니다. 잘못된 HTML을 붙여 넣었습니다. 이것은 하나의 udemy.com/blog/rename-a-file-in-linux입니다
Sander Van der

3
@SanderVanderZeeuw 당황. 이 사람들은 코스를 제공합니까? 불행히도 나는 연락 가능성이 보이지 않습니다. 이것이 작동하는지 쉽게 확인할 수 있습니다. 뿐만 mv *.txt *.tsv mv않습니다 (보통) 볼 *.txt또는 *.tsv쉘 - 확장 파일 이름을하지만. 이러한 와일드 카드로 확장되는 파일 수는 "무작위"입니다. 이것이 작동하는 유일한 상황은 이름 *.txt을 가진 파일이 (문자 그대로) *.tsv(따옴표없이 bash옵션을 nullglob설정하지 않아야 함 ) 이름의 파일이있는 경우 입니다.
Hauke ​​Laging

1
아니면 더 나쁘다. 하나가있는 경우 하나의 파일 이름 예 foo.txt하나의 이름이 baz.tsv(가) mv *.txt *.tsv기존 덮어 쓰게됩니다 .tsv파일을 ...
Runium

4

당신은 예를 들어, asd.txt그리고 qwe.txt당신이 명령을 실행할 때 디렉토리에있는 파일 mv *.txt *.tsv, 그것은라는 이름의 디렉토리에 두 파일을 이동하려고합니다 *.tsv. 그러한 디렉토리가 없기 때문에 오류가 발생합니다.


고마워, 이것은 부분적으로 명확 해집니다. 아직도 나는 그들이 mv가 다중에서 작동해야한다고 주장하는 너무 많은 매뉴얼 페이지를 보는 것이 이상하다고 생각합니다.
샌더 반 데르 Zeeuw

2

rename(1)

renamePerl의 제작자 인 Larry Wall의 perl 스크립트입니다. Perl 정규식을 사용하고 파일 이름으로 작동합니다.

rename 's/\.txt$/.tsv/' *.txt

설치

데비안 / 우분투

rename데비안 / 우분투에 설치해야 할 경우

sudo apt install rename

0

고려해야 할 또 다른 옵션은 다음을 사용하는 것입니다.

cp -p *.txt *.tsv
rm -f *.txt
  • 첫 번째 행 은 플래그를 사용하여 속성을 유지하면서 모든 *.txt파일을 복사합니다 .*.tsv-p
  • 두 번째 줄은 패턴이있는 모든 파일을 제거합니다 *.txt
  • 이 방법을 사용하려면 소스 파일과 대상 파일을 임시로 저장할 수있는 충분한 디스크 공간이 있어야합니다.
  • 이 방법은 mv파일이 다른 파티션에 있지 않으면 실제로 파일을 이동하지 않고 단순히 / directory / filename을 변경하는 것보다 느립니다 .
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.