mv가 존재하지 않을 경우 이동시킬 디렉토리를 작성하는 방법이 있습니까?


275

따라서 내 홈 디렉토리에 있고 foo.c를 ~ / bar / baz / foo.c로 옮기고 싶지만 해당 디렉토리가 존재하지 않으면 해당 디렉토리가 자동으로 생성되도록하는 방법이 있습니까? 당신은 입력해야합니다

mv foo.c ~/bar/baz/ 

모든 것이 잘 될까요? 해당 디렉토리가 존재하는지 확인하고 mkdir 및 mv를 호출하지 않는지를 확인하는 간단한 bash 스크립트로 mv의 별칭을 지정할 수있는 것처럼 보이지만 누군가 더 나은 아이디어가 있는지 확인하려고 생각했습니다.


답변:


294

이 하나의 라이너 (bash에서)는 어떻습니까?

mkdir --parents ./some/path/; mv yourfile.txt $_

세분화 :

mkdir --parents ./some/path

디렉토리 (모든 중간 디렉토리 포함)를 생성 한 후 다음을 수행합니다.

mv yourfile.txt $_

파일을 해당 디렉토리로 이동합니다 ($ _는 이전 쉘 명령에 전달 된 마지막 인수, 즉 새로 작성된 디렉토리로 확장됩니다).

다른 쉘에서 이것이 얼마나 멀리 작동하는지 잘 모르겠지만 찾을 대상에 대한 아이디어를 줄 수 있습니다.

이 기술을 사용한 예는 다음과 같습니다.

$ > ls
$ > touch yourfile.txt
$ > ls
yourfile.txt
$ > mkdir --parents ./some/path/; mv yourfile.txt $_
$ > ls -F
some/
$ > ls some/path/
yourfile.txt

32
'$ _'에 좋습니다.
dmckee --- 전 운영자 고양이

1
./어디에서나 중복에 대한 집착이 필요한 이유는 무엇 입니까? args는 .디렉토리 가없는 PATH의 명령이 아닙니다 ...
Jens

3
초보자를 위해,
부모

8
이상하게도 --parentsmacOS 10.13.2에서는 사용할 수 없습니다. 를 사용해야 -p합니다.
Joshua Pinter

1
./some/path/foo와 같은 파일을 이동하면 작동하지 않습니다. 이 경우 명령은 다음과 같아야합니다.mkdir -p ./some/path/foo; mv yourfile.txt $_:h
hhbilly

63
mkdir -p `dirname /destination/moved_file_name.txt`  
mv /full/path/the/file.txt  /destination/moved_file_name.txt

2
이 코드가 이해가되지 않는 유일한 사람입니까? 기존 파일에 대한 절대 경로를 재귀 적으로 생성 한 다음 (이 경로가 이미 존재 함) 파일을 위치 (예 : 존재하지 않는)로 이동합니다.
vdegenne

1
@ user544262772 GNU coreutils ' dirname에는 인수가 필요하지 않으며 순수한 문자열 조작입니다. 다른 배포판에 대해서는 말할 수 없습니다. 이 코드에 아무런 문제가 없습니다.
TroyHurts

이것이 가장 쉬운 자동화 방법이라고 생각합니다. for f in *.txt; do mkdir -p `dirname /destination/${f//regex/repl}`; mv "$f" "/destination/${f//regex/repl}; done
Kyle

23

mv 또는 mv.sh라는 스크립트로 저장

#!/bin/bash
# mv.sh
dir="$2"
tmp="$2"; tmp="${tmp: -1}"
[ "$tmp" != "/" ] && dir="$(dirname "$2")"
[ -a "$dir" ] ||
mkdir -p "$dir" &&
mv "$@"

또는 ~ / .bashrc 파일의 끝에 새 터미널마다 기본 mv를 대체하는 함수로 넣으십시오. 함수를 사용하면 매번 스크립트 파일을 읽을 필요없이 bash가 메모리를 유지할 수 있습니다.

function mv ()
{
    dir="$2"
    tmp="$2"; tmp="${tmp: -1}"
    [ "$tmp" != "/" ] && dir="$(dirname "$2")"
    [ -a "$dir" ] ||
    mkdir -p "$dir" &&
    mv "$@"
}

이들은 Chris Lutz의 제출을 ​​기반으로합니다.


3
이 질문에 가장 정확하게 대답합니다. 사용자는 향상된 mv명령을 원합니다 . 특히 스크립팅에 유용합니다. 즉, 검사를 실행하고 mkdir -p필요할 때마다 실행 하지 않아도됩니다 mv. 그러나에 대한 기본 오류 동작을 원 하므로 mv함수 이름을로 변경하여 mvp디렉토리를 언제 만들 수 있는지 알 수 있습니다.
Brian Duncan

최고의 솔루션 아이디어처럼 보이지만 구현은 많은 충돌을 일으 킵니다.
Ulises Layera

2
@UlisesLayera 알고리즘을보다 견고하게 수정했습니다. 지금 충돌해서는 안됩니다
Sepero

누군가 [ ! -a "$dir" ]내가 오른쪽 절반이 참으로 거짓으로 실험을 수행했다는 의미를 설명해 주시겠습니까 ?. ??? 다른 사람을 위해 tmp = "$ {tmp : -1}"은 파일의 마지막 문자를 가져 와서 경로 (/)가 아닌지 확인합니다.
bazz

@bazz "$ dir이 존재하지 않으면 계속"해야합니다. 불행히도, 당신은 맞습니다, "! -a"를 사용할 때의 버그가 있으며, 그 이유를 모르겠습니다. 코드를 약간 편집했으며 이제 작동합니다.
Sepero

13

당신은 사용할 수 있습니다 mkdir:

mkdir -p ~/bar/baz/ && \
mv foo.c ~/bar/baz/

자동으로 수행하는 간단한 스크립트 (예상치 않음) :

#!/bin/sh

# Grab the last argument (argument number $#)    
eval LAST_ARG=\$$#

# Strip the filename (if it exists) from the destination, getting the directory
DIR_NAME=`echo $2 | sed -e 's_/[^/]*$__'`

# Move to the directory, making the directory if necessary
mkdir -p "$DIR_NAME" || exit
mv "$@"

"? $ dirname이 ~ 바 / 바즈 /"나는 실행 내가 얻을 "/ 홈 / dmckee / 바"요 ... 여기에 원하는하지 않은
dmckee --- 전 사회자 고양이

@dmckee, 아, 맞아. 이 문제를 해결하는 방법에 대한 아이디어가 있습니까? ~ / bar / baz를 입력하면 (a) ~ / bar /로 복사하고 baz로 이름을 바꾸거나 (b) ~ / bar / baz /로 복사합니다. 업무에 더 적합한 도구는 무엇입니까?
strager

@ dmckee, regexp / sed를 사용하여 솔루션을 생각해 냈습니다. 원하는대로 작동합니까? =]
strager

$ # = 2가 아니라면 $ 2를 제외하고는 마지막 인수가 아닙니다. 마지막 인수를 인쇄하는 프로그램 la가 있습니다. cp 명령 버전에서 사용했습니다 (마지막 인수가 디렉토리가 아닌 경우 현재 디렉토리를 추가하기 위해). 현대의 쉘조차도 $ 1 .. $ 9 만 지원합니다. Perl 스크립트가 더 나을 수 있습니다.
Jonathan Leffler

@Leffler, True가 아님-bash가 9 개 이상의 인수를 지원한다는 것을 알고 있습니다 ($ {123} 사용하는 방법 중 하나). 나는 Perl을 모른다. 그래서 스스로 대답을 자유롭게해라. =]
strager

7

대답이 아니오 인 것 같습니다 :). 이 작업을 수행하기 위해 별명이나 기능을 만들고 싶지는 않습니다. 일회성이며 이미 mv명령 을 입력하는 중이기 때문에 잘 작동하는 것을 발견했습니다.

mv *.sh  shell_files/also_with_subdir/ || mkdir -p $_

mv실패하면 (dir이 존재하지 않는 경우 ) 디렉토리를 만듭니다 (이전 명령의 마지막 인수이므로 디렉토리도 마찬가지입니다 $_). 따라서이 명령을 실행 한 다음 up다시 실행하면 이번에 mv는 성공합니다.


5

아마도 다음 쉘 스크립트?

#!/bin/sh
if [[ -e $1 ]]
then
  if [[ ! -d $2 ]]
  then
    mkdir --parents $2
  fi
fi
mv $1 $2

이것이 기본 부분입니다. 인수를 확인하기 위해 비트를 추가 할 수도 있고 대상이 존재하거나 소스 디렉토리가 존재하지 않거나 존재하지 않는 경우 (예 : 존재하지 않는 것을 덮어 쓰지 않는 경우) 동작을 변경하고자 할 수 있습니다. .


1
코드가 없으면 디렉토리가 존재하지 않으면 이동이 수행되지 않습니다!
strager

1
그리고 mkdir에 "-p"플래그를 놓쳤다.
dmckee --- 전 운영자 고양이

디렉토리가 존재하지 않는 경우 디렉토리를 이동하려는 경우 왜 작성합니까? (-p 플래그 수정)
크리스 루츠

스크립트를 실행할 때 $ 2 디렉토리가 존재하지 않으면 스크립트가 작성되지만 파일은 복사되지 않습니다.
트래 거

그는 간단한 구성을 제공하고 확장 방법에 대한 정보를 추가했습니다. 왜 투표하지?
ypnos

5

rsync를 명령은 트릭을 할 수있는 마지막 디렉토리 만 대상 경로가의 대상 경로에 대한 예를 들어, 존재하지 않는 ~/bar/baz/경우 bar존재하지만 baz, 다음 명령을 사용할 수 없습니다 :

rsync -av --remove-source-files foo.c ~/bar/baz/

-a, --archive               archive mode; equals -rlptgoD (no -H,-A,-X)
-v, --verbose               increase verbosity
--remove-source-files   sender removes synchronized files (non-dir)

이 경우 baz디렉토리가 없으면 작성됩니다. 그러나 두 경우 barbazrsync를 존재하지 않는 오류가 발생합니다 :

sending incremental file list
rsync: mkdir "/root/bar/baz" failed: No such file or directory (2)
rsync error: error in file IO (code 11) at main.c(657) [Receiver=3.1.2]

따라서 기본적 rsync -av --remove-source-files으로에 대한 별칭 으로 사용 하는 것이 안전해야합니다 mv.


4

가장 간단한 방법은 다음과 같습니다.

mkdir [directory name] && mv [filename] $_

다운로드 디렉토리 ( ~/download) 에있는 pdf 파일을 다운로드 했고 존재하지 않는 디렉토리로 모든 파일 을 옮기고 싶다고 가정 해 봅시다 (my_PDF ).

다음 명령을 입력합니다 (현재 작업 디렉토리가 ~/download).

mkdir my_PDF && mv *.pdf $_

다음 과 같이 서브 디렉토리를 작성하려는 경우 -p옵션을 추가 할 수 있습니다 mkdir. (라는 서브 디렉토리를 작성하려는 경우 python) :

mkdir -p my_PDF/python && mv *.pdf $_

2

더 조용하지만 작동하는 방법 :

mkdir -p $2
rmdir $2
mv $1 $2

대상 파일 이름을 공유하는 임시 디렉토리를 포함하여 mkdir -p로 디렉토리를 작성한 다음 간단한 rmdir로 해당 파일 이름 디렉토리를 제거한 다음 파일을 새 대상으로 이동하십시오. 나는 dirname을 사용하는 대답이 아마도 최고라고 생각합니다.


예, 좀 어리석은 일입니다. :-) $ 2가 (원래 질문에서와 같이) 디렉토리이면 마지막 디렉토리가 삭제되므로 'mv'는 실패하므로 비참하게 실패합니다. 그리고 $ 2가 이미 존재하면 삭제하려고 시도합니다.
Tylla

감사! 이것은 내가 달성하기 위해 정확히 필요한 것입니다 : mv ./old ./subdir/new subdir이 아직 존재하지 않는 곳
Mike Murray

2
((cd src-path && tar --remove-files -cf - files-to-move) | ( cd dst-path && tar -xf -))

1

암호:

if [[ -e $1 && ! -e $2 ]]; then
   mkdir --parents --verbose -- "$(dirname -- "$2")"
fi
mv --verbose -- "$1" "$2"

예:

인수 : "d1" "d2 / sub"

mkdir: created directory 'd2'
renamed 'd1' -> 'd2/sub'

1

상위 디렉토리 foo.c가있는 새 디렉토리 baz로 이동 합니다 bar.

mv foo.c `mkdir -p ~/bar/baz/ && echo $_`

필요에 따라 중간 디렉토리를 작성 하는 -p옵션 mkdir입니다.
없이-p경로 접 두부에 모든 디렉토리가 이 L 존재해야합니다.

백틱 내부의 모든 ``것이 실행되고 명령의 일부로 출력이 인라인으로 반환됩니다. 아무것도 반환하지 않기
때문에 mkdir의 출력 만 echo $_명령에 추가됩니다.

$_이전에 실행 된 명령에 대한 마지막 인수를 참조합니다.
이 경우 명령에 ~/bar/baz/전달 된 새 디렉토리 ( ) 의 경로를 반환합니다 mkdir.


대상을 지정하지 않고 아카이브의 압축을 풀고 demo-app.zip현재 디렉토리를 제외한 모든 파일 을이라는 새 디렉토리 로 이동하고 싶었습니다 demo-app.
다음 줄은 트릭을 수행합니다.

mv `ls -A | grep -v demo-app.zip` `mkdir -p demo-app && echo $_`

ls -A숨겨진 파일을 포함하여 모든 파일 이름을 반환합니다 ( 암시 적 ... ).

파이프 기호 |ls명령 출력 을 grep( 명령 행 일반 텍스트 검색 유틸리티 ) 로 파이프하는 데 사용됩니다 . 플래그는 지시 찾아 제외한 모든 파일 이름을 반환합니다 . 해당 파일 목록은 명령 줄에 move 명령의 소스 인수로 추가됩니다 . 대상 인수 는를 사용하여 참조 및 출력으로 전달 된 새 디렉토리의 경로 입니다.
-vgrepdemo-app.zip
mvmkdir$_echo


1
이것은 좋은 수준의 세부 사항과 설명이며 특히 첫 번째 게시물입니다. 감사!
Jeremy Caney

@JeremyCaney 감사합니다! 도와 드리게되어 기쁩니다!
Evan Wunder

0

중괄호 확장을 사용할 수도 있습니다.

mkdir -p directory{1..3}/subdirectory{1..3}/subsubdirectory{1..2}      
  • 3 개의 디렉토리 (directory1, directory2, directory3)를 작성합니다.
    • 그리고 그들 각각에 두 개의 하위 디렉토리 (subdirectory1, subdirectory2),
      • 그리고 그들 각각에는 두 개의 서브 서브 디렉토리 (subsubdirectory1 및 subsubdirectory2)가 있습니다.

bash 3.0 이상을 사용해야합니다.


5
흥미롭지 만 OP의 질문에 대답하지 않습니다.
Alexey Feldgendler

0
$what=/path/to/file;
$dest=/dest/path;

mkdir -p "$(dirname "$dest")";
mv "$what" "$dest"

1
독립 실행 형 sh 스크립트로 만들려면 $ dest와 $ src를 $ 1과 $ 2로
바꾸십시오

0

내 하나의 문자열 솔루션 :

test -d "/home/newdir/" || mkdir -p "/home/newdir/" && mv /home/test.txt /home/newdir/

0

명령을 연결할 수 있습니다 : mkdir ~/bar/baz | mv foo.c ~/bar/baz/
또는 쉘 스크립트는 다음과 같습니다.

#!/bin/bash
mkdir $2 | mv $1 $2

1. 텍스트 편집기를 엽니 다
. 2. 셸 스크립트를 복사하여 붙여 넣습니다 .
3. 스크립트 디렉토리 를 mkdir_mv.sh저장하십시오
. 4. 스크립트 디렉토리를 입력 하십시오. cd your/script/directory
5. 파일 모드 변경 : chmod +x mkdir_mv.sh
6. 별명 설정 : alias mv="./mkdir_mv.sh"
이제 명령을 실행할 때마다 mv디렉토리 이동이 없으면 작성됩니다.


0

다른 답변의 의견을 바탕으로 내 쉘 함수가 있습니다.

# mvp = move + create parents
function mvp () {
    source="$1"
    target="$2"
    target_dir="$(dirname "$target")"
    mkdir --parents $target_dir; mv $source $target
}

.bashrc 또는 이와 유사한 곳에 포함시켜 어디서나 사용할 수 있습니다.

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