mv가 파일 모음을 하나의 일반 파일로 옮기는 것을 방지하는 방법은 무엇입니까?


17

방금 바보 같은 실수로 오디오 컬렉션의 작은 부분을 잃어 버렸습니다. :-(
글쎄, 나는 상당히 최근의 백업을 받았지만 여전히 짜증났다. 당신과는 별도로, 장난을 저지른 다른 범인 mv은 다음과 같이 보일 것이다.

오디오 파일에는 특정 구성표가 있습니다.

ARTIST - Some Title YY.mp3

경우 YY2 자리 연도 사양입니다.

mkdir 90<invisible control character>

(이 순간까지, 나는 실제로 보이지 않는 1/3 초과 문자를 입력했다는 것을 몰랐습니다 ...!)
모든 디렉토리를 하나의 디렉토리에 두는 대신 1990 년대의 모든 음악을 하나의 디렉토리에두기를 원했습니다. 그래서 나는 타이핑했다 :

find . -name '* 9?.mp3' -exec mv {} 90 \;

무슨 일이 있었는지 알기 힘들지 않습니까? ->
(비참한) 결과는 처녀 디렉토리가 '90라는 뭔가 '(와 뭔가 은 "보이지 않는"제어 문자 인)과 하나 개의 파일 이라고' '(90)를 덮어 n 개의 시간을.

모든 파일이 사라졌습니다. :-(((분명히))

Wish mv는 대상 "file"의 서명 (* NIX : Everything Is A File 기억 )이 (예 :)로 시작 하는지 여부를 제 시간에 확인 했습니다 . 그리고 물론 목적지 가 존재 하는지 여부 . 당신은 단순히 전술 시나리오의 변형이 잊고 에 먼저 디렉토리. (물론, 당신은 그것이 있다고 가정했습니다 ...)d------drwxr-xr-xmkdir

심지어 우리의 애완 동물 - 증오 OS는 자본으로 시작 W 않습니다 DO THIS. 원하는 경우 대상 유형 (파일? 디렉토리?)을 지정 하라는 메시지가 표시 됩니다.

따라서, 우리가 * NIXers가 mv이러한 종류의 가장 원치 않는 놀라움을 피하기 위해 여전히 " 스크립틀릿" 을 작성해야하는지 궁금합니다 .


2
모든 파일이 사라지는 것은 아닙니다. 최소한 하나 .mp3는 name으로 90있어야하며 백업이없는 것일 수 있습니다.
Anthon

2
넌 냉소적 인 유머 감각을 가지고있어 :-P 글쎄, 그것은 내 OP에서 굵은 글씨로 "하나의 단일 파일"이라는 파일이었습니다. :)
syntaxerror

2
mv기술적으로 문제가 아니며 일련의 파일을 이동하고 있다는 것을 모릅니다. mv각 파일마다 한 번씩 실행 중입니다. 그것이 find -exec ;작동 하는 방식입니다. 당신이 find -exec +(일부 의견에서와 같이) 사용 mv 했다면, 하나 이상의 주장을하자마자 비명을 질렀을 것입니다.
Etan Reisner

mv각 단일 파일에 대해 실행 하는 것이 처음에는 약간 덜 생각되는 것처럼 보일 수 있지만 소스 파일이 다양한 하위 디렉토리에 흩어져 있으면 (이전에 말했듯이) 유일한 해결책이 될 것입니다. 필자의 테스트 사례에서 소스 파일이 모두 하나의 디렉토리에 있다고해서 이것이 실제 테스트 사례 라는 의미는 아닙니다 . 나중에 간단하게 설명 할 수 있기 때문에 실제로는 단순화입니다. 또한 길이가 짧아 질문을 읽는 데 시간이 덜 걸립니다. :)
syntaxerror

mv대상이 존재해야하는 이유는 무엇 입니까? mv oldfile newfile파일의 이름을 바꾸는 방법이며 newfile이미 존재하며 디렉토리가 될 것으로 예상 되지 않습니다.
Barmar

답변:


37

/파일을 디렉토리로 이동하려는 경우 대상에 a 를 추가 할 수 있습니다 . 디렉토리가 존재하지 않으면 오류가 발생합니다.

mv somefile somedir/
mv: cannot move ‘somefile’ to ‘somedir/’: Not a directory

디렉토리가 존재하면 파일을 해당 디렉토리로 이동합니다.


4
정말 고맙습니다! 그것은 내 미래의 생명의 은인이어야합니다. 내가 당신 께 신세를지는 거죠. (참고로, 내 친구가 몇 년 전에 똑같은 실수를했기 때문에 혼자가 아니라고 느낍니다.)
syntaxerror

1
또한 특정 쉘을 사용할 때 파일 이름을 자동 완성하는 탭 옵션이 있습니다. 디렉토리 이름을 기억하지 못하고 최근에했던 것처럼 엉망을 원하지 않으면 디렉토리 이름과 HIT TAB 의 문자를 두 개 입력하십시오 . 그럼 당신은 할 수있다, 그것이 존재하기 때문에 자동 완성이 넣어를 ...
Andyz 스미스

@AndyzSmith 글쎄, 바로 그거야. 복잡한 디렉토리 또는 경로에는 TAB 만 사용 하고 2 문자 유형에는 사용하지 않는 것이 습관 입니다. :) 그러나 생각해보십시오 ... 아마도 후자의 경우도 고려해야합니다. 지금부터.
syntaxerror

20

GNU coreutils mv에는 이미 디렉토리로 이동하도록 지정하는 옵션이 있습니다 : -t/ --target-directory. 해당 옵션에 대한 인수가 존재하지 않으면 mv모든 파일을 동일한 파일 이름으로 이동하는 대신 불평합니다.

나는 당신의 발동기를 다음과 같이 썼을 것입니다 :

find . -name '* 9?.mp3' -exec mv -t 90 {} +

+대신 \;많은 파일 이름을 모아서 실행 속도를 높이는 대신을 사용하십시오 .


감사. (그것이 다시 GNU-isms 중 하나가 아니기를 바랍니다.)
syntaxerror

2
@syntaxerror. GNUism입니다. POSIXly :find . -name '* 9?.mp3' -exec sh -c 'exec mv "$@" 90/' sh {} +
스테판 Chazelas

이 SNEAKY 원 라이너에 대해 대단히 감사합니다! 내가 당신에게 준 +5라고 생각하십시오. :) 많은 시행 착오 시도를 불필요하게 만들 것입니다 .--- 그리고 내가 그 말을 한 이유를 너무 잘 알고 있습니다. POSIX (너무 드물게 발생하지는 않음) 인 머신에 있어야합니다. 다음 문제가 생길 것입니다. :)
syntaxerror

1
@syntaxerror이 답변으로 문제가 해결되면 잠시 후 왼쪽의 투표 수 아래에있는 확인 표시를 클릭하십시오. 이는 문제가 해결되었다는 것을 모든 사람에게 알리고 사이트에서 감사를 표하는 방식입니다. 나는 당신의 다른 답변 된 질문들 중 일부만이 답변을 받아 들였다는 것을 알았습니다.
Anthon

아니요, 단순히 목적입니다. 나는 대답을 받아 들일 때까지 몇 주 또는 때로는 2 개월을 자주 기다립니다. 그 이유는 매우 지식이 많은 사람들이 매우 많은 일정을 가지고 있으며 몇 주 후에 (보통 최상의) 답변을 줄 시간을 찾을 수 있기 때문입니다. 그래서 나는 항상 그들이 기다리는 것을 기다리는 것이 정중하다고 생각합니다. 글쎄, 그들이 정말로 그렇지 않으면, 나는 확인 표시를 누르는 것을 망설이지 않을 것입니다. 게다가, 나는 왜 어떤 사람들이 SE + 그 풍미에 대해 서두르는 지 알지 못합니다. 쉬운 일이야. 총을 뛰지 마십시오. :) 이것은 당신의 상사가 당신을 누르는 것이 아닙니다.
syntaxerror

10

또한 일반적으로 나중에 실수로 덮어 쓰지 않도록 계획 할 경우 -i 옵션이 mv있습니다. 나는 개인적으로 어떤 단점을 생각할 수 없다

alias mv='mv -i'

그런 다음 무언가를 덮어 쓰려면 -f옵션을 전달하면 됩니다.

별명은 다음과 같은 경우가 아닌 대화식 쉘에 명령을 직접 입력 한 경우에만 적용됩니다. find . 당신은 실행할 수 있었다

find . -name '* 9?.mp3' -exec mv -i {} 90 \;

그런 다음 mv기존 파일을 덮어 쓰려고 했는지 묻는 메시지가 나타납니다 .


4
또는 아마 당신이 알지 못했던 것처럼 대신에 ´ \ mv`를 입력하십시오 mv. 이 덜 알려진 "트릭"은 백 슬래시가 앞에 붙은 명령이 별명 정의 를 무시 하도록 합니다.
syntaxerror

물론에 대해 이야기하고 있다면 별칭을 보지 않기 때문에 find ... -exec mv ...만들어야합니다 ~/bin/mv(또는 다른 적절한 디렉토리) . /bin/mv -i "$@"find ... -exec
G-Man, 'Reinstate

이 경우 선호합니다 env mv. 타이핑이 적습니다. :) 로컬 키보드 레이아웃에서는 슬래시를 위해 SHIFT 키를 눌러야하므로 항상 "슬래시없는"버전을 선호합니다 (해당되는 경우).
syntaxerror

1
@syntaxerror : BTW, 의견에 답할 때 (새로운 의견으로),“@ G-Man”에서와 같이 저자 이름 앞에“@”를 언급하는 것이 일반적입니다. 그렇게하면 알림을받습니다. Jenny D의 의견에 의해 통보를 받았기 때문에 마지막 의견에 반 시간 내에 답변 할 수있었습니다.“@ StéphaneChazelas”와 같이 전체 이름 (공백없이)을 약어로 사용하거나 사용할 수 있습니다. 게시물 작성자에게 해당 게시물에 대한 의견이 자동으로 통보됩니다. 참고 항목 코멘트에 답장 의 단락 이 도움말 페이지를 .
G-Man, 'Reinstate

1
죄송합니다. 하루 동안 인터넷이 없었습니다. @ G-Man mv처음에 특정 위치에 개인 버전을 설치 $PATH하는 것이 더 깔끔한 솔루션 이라는 데 동의합니다 . 반면에 나는 mv대화 형 쉘에서 부주의하게 일어 났습니다 (빠르게 발생하기 때문에). 루프 findfor루프 스크립트 와 같이 더 복잡한 것을 작성하는 순간 , 나는 echo무언가를 깨뜨리지 않기 위해 건식 실행을 사용하는 경향이 있습니다 (을 사용하여 ). 그런 경우에는 mv이미 손을 잡고있을 필요가 없습니다 .
ayekat

7

위의 훌륭한 답변 외에도 파일 이동 여부에 대한 질문을받지 못한 이유를 분명히하고 싶습니다.

파일을 새 이름으로 옮기고 해당 이름이 디렉토리가 아닌 경우,mv 파일 이름을 새 이름으로 바꿉니다.

여기서 문제는 모든 파일에 대해 한 번이 아니라 파일 당 한 번 find실행 하는 데 사용되었다는 것입니다.mv 입니다.

대신에을 수행 mv *90.mp3 90한 경우 mv "대상 파일이 디렉토리가 아닙니다"라는 오류 메시지와 함께 실패했을 것입니다.

또 다른 조언은 대상 경로를 입력 할 때 탭 완성을 사용하는 것입니다. /대상 이름에 대상 을 추가하여 대상이 디렉토리인지 여부를 표시합니다 . mv -i기존 파일을 덮어 쓸지 묻는 메시지를 표시 할 수도 있습니다 .


대신 mv *90.mp3 90에을 수행 하면 "대상 파일이 디렉토리가 아닙니다"라는 오류 메시지와 함께 mv가 실패했을 것입니다. 응, 왜 그렇게 복잡한가? 나는 당신의 라인을 사용하고 행복합니다. 그러나이 사소한 경우에만. :) 이것이 일반적인 질문 방식이기 때문에 간단하게하기 위해 질문 범위를 좁혔습니다. 아무도 이의를 제기하지 않았다 find지금까지 90의 파일뿐만 아니라에 흩어져 될 수 있음을 고려하여 다양한 하위 디렉토리 뿐만 아니라 내가 "캐치"를 원한다. 경우 에만 그들은 있다면 항상 하나의 소스 디렉토리에, 당신의 mv라인을 적용한다.
syntaxerror

@syntaxerror 매우 사실입니다-나는 이것이 mv당신이 선택한 도구에 대한 비판이 아니라 행동 방식의 예라고 생각했습니다 .
Jenny D

1
당신은 아마 결합 무언가를 만들 수 findmv, 예를 find /music -type d -exec mv {}/*90.mp3 targetdir\;나는 그것을과 복잡함을, 간단하게 사용하고 싶지만 지금은 조금 느낌이 - -i또는 -t더 효율적입니다
제니 D를

1
@Jenny : find . -type d -exec mv {}/*9?.mp3 target \;예제가 제대로 작동하면 파일이 하나만 포함 된 각 디렉토리마다 mv명령이 표시 될 위험이 있습니다. 따라서 모든 파일 (마지막 파일 제외)이 손실됩니다. mv file target*9?.mp3
G-Man, 'Reinstate

4
@ syntaxerror : 문제가 발생하는 전체 42,000 줄 스크립트가 아니라 문제의 핵심 부분을 노출하려는 노력에 박수를 보냅니다. 그러나, 당신이 한 경우에도 모두에게 뭔가하고 싶은 *.mp3디렉토리 트리에있는 파일을, 당신은 할 수 shopt -s globstar에서 다음 명령을 실행 **/*.mp3(가) - **유사한 역할을합니다 find.
G-Man, 'Reinstate

1

대체 범용 전략으로 이러한 종류의 작업을 임시 스크립트로 전환하는 것이 좋습니다. 나는 결과를보고 직접 명령으로 find바꾸어 mv실행하기 전에 내가하고있는 일을 이해하고 싶습니다. 예.

find . -name '* 9?.mp3' > tmp
vim tmp

이제 파일 이름 목록을 살펴보고 파일 내용을 셸 명령으로 다시 작성할 수 있습니다.

  • 파일 내용을 한 줄에 넣으십시오. ggVGJ
  • 접두사 : Imv [esc]
  • 추가 : Asomedir/ [esc]
  • 파일을 저장하십시오. 다시 읽으십시오. 숨을.
  • source tmp명령 행에서 실행 하십시오.

보수적 인 전략이지만 잘못 입력 -exec하거나sed 명령하거나 쉘 확장을 잘못 이해 천천히 일관된 접근 방식을 선호합니다.

다시 말해 : 나는 너무 비겁하게 사용하기 어렵다 -exec.


1
:%s/.*/"&"/이 경우 모든 파일 이름에 최소한 하나의 공백이 포함되어 있으므로 단계를 생략했습니다 .
G-Man, 'Reinstate

1
파일 이름에 공백이나 다른 특수 문자가 포함되어 있으면 물릴 것입니다. 당신은 제대로 인용해야합니다. 명령 목록을 검토해도 특히 오류가 발생하지는 않습니다. echo mv대신 실행 하고 마음에 드는 경우 mv제거하는 등 명령을 실행하기 전에 검토하는 훨씬 더 좋은 방법 echo이 있습니다.
Gilles 'SO- 악한 중지

공백이있는 파일 이름과 같은 실수를 발견하면이 기술이 도움이됩니다 :-)
Tom Rees

0

다른 옵션 :

-n, --no-clobber는 기존 파일을 덮어 쓰지 않습니다.

-i와 동일하지만 묻지 않고 실패합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.