Linux에서 디렉토리를 복사 할 때 왜 -r 재귀가 필요합니까?


47

내 질문은 -r디렉토리의 사본을 만들 때 (재귀) 플래그 를 사용해야하는 이유는 무엇입니까? 즉, 왜 이렇게 :

$ cp -r dir1 copyDir1

디렉토리를 복사 할 때이 동작을 원하지 않는 경우는 언제입니까?

디렉토리의 재귀 복사본이 실제로 "기본"동작이 아닙니 다. 우리가 항상 원하는 행동?

이것이 불필요한 플래그 인 것 같습니다.


파일과 폴더도 복사 할 필요가 없습니까?
QuyNguyen2013

이것이 개선 될 것이라고 생각되면 개발자 채널에이 요청을 다시 게시 할 수 있습니다. 그렇지 않으면 아마도 오래 전에 프로그래밍되었을 것입니다.
블로거

@blogger 오래 전에 프로그래밍되었지만 이유가 있습니다. 누군가가 명령 행 환경에서 기본 작업을 수행하려는 경우 시스템 장애를 피하는 것이 어려운 것처럼 작업이 쉬워야합니다. 일부 명령 줄 사용자 상호 작용 규칙이 존재하는 데는 충분한 이유가 있습니다. 나는이 개념을 내 대답으로 확장합니다.
JakeGould


동일한 기능rm

답변:


58

파일 시스템이 작동하는 방식에서 디렉토리는 실제로 파일을 포함하는 폴더가 아니라 디렉토리에 연결된 "하위"파일에 대한 inode 포인터포함 하는 파일입니다 . 파일 시스템 관점에서 파일은 파일이지만 디렉토리는 연결된 파일 목록을 포함하는 파일 일뿐입니다.

따라서 명령 행 관점에서 다음을 수행하십시오.

$ cp dir1 copyDir1

기본적으로라는 dir1파일을이라는 새 파일로 복사하는 것을 의미 합니다 copyDir1. 파일 시스템에 관한 dir1한 어쨌든 파일 일뿐입니다. "디렉토리"라는 사실은 파일 시스템이 실제로 dir1그 비트 더미가 실제로 무엇인지 확인 하는 경우에만 분명합니다 .

-r플래그는 파일 / 디렉토리 트리 아래로 반복적으로 롤에 파일 시스템을 지시하고 새로운 위치로 해당 파일의 "아이"가 될 수있는 및 모든 내용을 복사합니다.

이것이 왜 불필요한 지 또는 중복 적인지에 대해, 이것은 실제로 파일 시스템을 다루는 역사적인 방법으로 귀결됩니다. 모든 유형의 사용자 관련 오류로부터 안전한 시스템을 만들뿐만 아니라; 우발적이며 의도적입니다.

즉, ~/bin홈 디렉토리에 파일을 복사하려고하지만 실수로 실수를하지 ~않았으므로 실수로 파일을 삭제 했다고 가정 해 보겠습니다 /bin.

cp /bin/ ~/copy_of_bin

플래그 /bin의 필요성과 결합 된 디렉토리 의 "안전망" -r을 사용하면 시스템의 전체 2 진 루트를 홈 디렉토리에 실수로 복사하지 않아도 됩니다. 안전망이 존재하지 않으면 경미한 재난이 발생할 수 있습니다.

여기서 논리는 GUI 이전의 그래픽 사용자 인터페이스 (GUI) 그래픽 / 행동 규칙이 잠재적으로 시스템을 죽일 수있는 사용자가 만든 실수를 피하기 위해 설정되어야한다는 것입니다. 그리고 -r깃발을 사용하는 것도 이제 그 중 하나입니다.

그것이 불필요한 것처럼 보인다면, 최신 GUI 시스템보다 더 이상 볼 필요가 없습니다. Linux 파일 시스템 위에 놓을 수 있습니다. GUI는 파일과 디렉토리를 쉽게 드래그 앤 드롭 할 수 있도록하여 이와 같은 기본 사용자 문제를 해결합니다.

그러나 텍스트 기반 인터페이스 영역의 경우, 해당 세계의 많은 "사용자 경험"은 기본적으로 사용자를 계속 점검하여 잠재적 인 재난을 피할 수 있도록하는 논리적이고 Hueristic 기반의 도로 충돌입니다.

마찬가지로 Linux / Unix 파일 시스템 에 기본적으로 설정된 777권한과 sudo권한 이없는 이유 와 사용자가 777권한을 설정 하거나 모든 사람에게 sudo권한을 부여 할 때 실제 시스템 관리자가이기는 방법 . 이것들은 시스템이 안정적이고 가능한 한 "사용자 증명"을 보장하기 위해 수행하는 기본 작업입니다. 이러한 규칙을 단락시키려는 사람은 누구나 모르더라도 시스템을 손상시킬 수 있습니다.

추가 정보 : Unix Stack Exchange 사이트의 또 다른 대답 은 디렉토리의 비재 귀적 사본에 문제가있는 이유를 잘 설명합니다. 강조는 내 것입니다.

-R 플래그가 없으면 파일을 복사하는 것이 가능합니다. 누군가 재귀 적으로 디렉토리를 복사하지 않으려 는 경우가 드물기 때문입니다. 동일한 디렉토리 구조. 그것이 사람들이 원하는 것은 아니며, 실제로 이것을 수행하는 별도의 프로그램이 있기 때문에 (ln), 비재 귀적 디렉토리 사본은 허용되지 않습니다.

따라서 디렉토리가 실제로 내부에 inode 항목이있는 파일 인 경우 해당 파일의 직선 사본을 만드는 것은 하드 링크의 작동 방식과 동일합니다. 어느 누구도 원하는 것이 아닙니다.


19
나는 개인적으로 그것의 "보호"측면이 냄새 테스트를 통과하지 못한다고 생각합니다. 어떤 사람은 쉽게 입력 할 수 있습니다 cp -r /bincp-r ~/bin. 깃발 자체는 실수를 막거나 반드시주의를 기울이는 사람을 만들지 않습니다. 실수를 방지하려면 cp 명령을 사용하여 문제의 노드를 쉽게 확인하고 "이 디렉토리입니다. 모든 내용을 지정된 위치에 복사 하시겠습니까? /엔)?" 안전망 . 디렉토리에 -r을 요구하면 무엇보다 많은 코드가 줄어 듭니다.
JDL

12
맨홀과의 비유. @JDL이 말했듯이 문제의 플래그는 경로의 오타를 방지하기 위해 아무 것도하지 않습니다. 다른 명령과의 일관성을 이유로 이유를 받아들이는 것이 더 좋을지 모르지만 실제 이유는 "이것이 처음 작성된 방식이며 이제는 너무 많은 것들이 그 행동에 의존하여 변경이 불가능합니다"라는 느낌을 받았습니다.
기본

7
디렉토리 를 이동할 때 -r이 필요 하지 않습니다 . unix.stackexchange.com의 링크 된 답변이 훨씬 더 중요하다고 생각합니다. 비 재귀 사본과 동등한 것은 두 번째 디렉토리를 가지며 디렉토리 트리 내의 모든 파일에 대한 하드 링크를 갖는 것입니다.
gerrit

2
내가 실수하지 않은 경우, -r은 GNU 확장이었습니다. 역사적인 UNIX cp 재귀 적 사본을 가지고 있다고 생각하지 않습니다. 이것이 rsync 명령의 이유 중 하나였습니다 .
Mei

2
@JakeG 기본 개념을 이해할 수 있습니다. 그러나 문제의 명령에 -r 플래그가 추가 안전을 제공한다는 생각에 반대합니다. 내 경험상, 커맨드 라인 리눅스 명령은 본질적으로 안전하지 않습니다. 안전은 시간이 지남에 추가되었습니다. 리눅스 디자인에 내재 된 안전은 권한 시스템과 루트로 계속 실행되는 것에서 비롯됩니다. 루트로 실행하지 않는 것은 디자인보다 관습에 가깝습니다. 이 컨벤션은 대부분의 새로운 Linux 설치 프로그램에서 지원되지만 항상 그런 것은 아닙니다.
JDL

19

이것이 우리가 거의 항상 원하는 행동이라는 것은 매우 사실입니다. 그러나 이것이 반드시 재귀 적으로 복사하는 것이 기본 행동이어야한다는 것을 의미하지는 않습니다.

나는 그 이유 cp유닉스 철학에 뿌리를 둔 것처럼 행동 한다고 생각 한다 . 유닉스 는 인터페이스와 구현 모두에서 간단한 프로그램뿐만 아니라 한 가지 일을 잘 수행하는 프로그램을 선호한다 (때로는 더 나쁘다 라고 함 ).

여기서 퍼즐의 핵심 부분은 cp디렉토리를 복사하지 않고 cp파일 (및 파일 )을 복사 한다는 것을 깨닫고 있습니다. 디렉토리 를 복사하려면 각 디렉토리의 파일을 복사하기 위해 cp 재귀 적으로 호출합니다 .

물론, "디렉토리 복사"와 "재귀 적으로 파일 복사"의 차이점은 사용자 관점에서 볼 때 전혀 아무것도 아니지만 이 인터페이스를 사용하면 구현이 단순하게 유지 됩니다.

cp디렉토리를 복사 할 수있게 되면 곧 디렉토리에만 적합한 기능을 더 추가하려고합니다. 예를 들어로 끝나는 파일 이름 만 복사 할 수 있습니다 .sh. 필연적으로는이 리드 팽창기능 크리프 우리는 다른 운영 체제에서 사용되는 - 제작 소프트웨어가 느리고, 복잡하고 오류가 발생하기 쉬운.

또 다른 장점은 -r인터페이스 아래에서 실제로 발생하는 상황을 사용자가 이해하는 데 도움 이된다는 것입니다. 이것의 좋은 부작용은 재귀 작업의 개념을 배우면 그것을 지원하는 다른 도구에 대해 배울 때 약간의 작업이 필요하다는 것입니다 (예 : 등 grep)


어떤 사람들은 구현 세부 사항을 사용자에게 노출하는 것이 좋지 않으며 더 많은 기능을 갖는 것이 좋다고 확실히 말할 것입니다 . 여기서 나의 의도는 단지이 행동의 이론적 근거를 설명하는 것일 뿐이므로 어느 쪽이든 논쟁하려고하지 않습니다.


2
+1 “… 한 가지 일 을 잘해라 …” 이것을 진술 해 주셔서 감사합니다!
JakeGould

5

디렉토리와의 상호 작용을 통해 단일 파일이 아닌 디렉토리와 상호 작용하고 있음을 알 수 있습니다.

예를 들어 :

$ tree
.
└── folder1
    └── sub1
        └── subsub1

3 directories, 0 files
$
$ cp folder1/ folder2
cp: folder1/ is a directory (not copied).
$
$ mkdir blah
$ cp blah/ blah2
cp: blah/ is a directory (not copied).
$ rm blah/
rm: blah/: is a directory

따라서 폴더를 성공적으로 복사하려면 폴더와 폴더 참조와 관련된 객체가 모두 포함되므로 폴더를 파일 모음처럼 취급해야합니다.

$ cp -r folder1/ folder2
$ rm -rf folder1

3

기본값을 변경하면 수천 개의 쉘 스크립트가 중단됩니다. 이는 잘 알려진 기본 동작에 대한 POSIX 및 SUS 요구 사항으로 이어집니다.

그 이유는 다양한 UNIX 브랜치에서 cp, ln 및 mv 명령 (대부분의 오래된 UNIX 시스템에서 모두 동일한 바이너리)이 개발 되었기 때문입니다. 때 -r나타났다 (초기 cp디렉토리를 복사 할 수있는 옵션을 가지고 있지 않았고, 여기에 초기 CP 남자 페이지입니다 없이 -r또는 -R), 특수 파일, 심볼릭 링크와 파일 시스템의 다른 변덕을 처리하는 다양한 차이가 있었다.

에서 사용되는 The Open Group 기본 사양 문제 7 :

이 표준의 이전 버전에는 파일 계층을 복사하기위한 -r 옵션에 대한 지원이 포함되었습니다. -r 옵션은 BSD 및 BSD 파생 시스템에서 기록적인 방법입니다. 이 옵션은 POSIX.1-2008에 의해 더 이상 지정되지 않지만 일부 구현에 존재할 수 있습니다. -R 옵션은 -r 옵션과 밀접한 동의어로 추가되었으며 재귀 디렉토리 하강을 수행하는이 POSIX.1-2008 볼륨의 다른 모든 옵션과 일관성을 유지하도록 선택되었습니다.

-R과 제거 된 -r 옵션의 차이점은 일반 및 디렉토리 이외의 파일 유형의 cp에 의해 처리됩니다. -옵션이 특수 파일을 처리하여 과거 구현과이 POSIX.1-2008 볼륨에서 정의한 -R과 동일한 기능을 가진 -r을 지원하도록 선택한 파일을 처리하는 방법은 구현에 따라 정의되었습니다. 역사적인 이유로 원래 -r 플래그는 특수 파일을 일반 파일과 다르게 처리하지는 않았지만 항상 파일을 읽고 내용을 복사했습니다. 이것은 특수 파일 형식이있을 때 명백한 문제가있었습니다. 예를 들어, 문자 장치, FIFO 및 소켓입니다.

실제로 일부 사람들은 다음을 정기적으로 사용합니다.

cd dir1 ; tar -cf - . | (cd dir2 ; tar -xpf -)

cp -r구현이 임의의 머신에서 사용되는 것을 신뢰하지 않기 때문 입니다. 또는 그들은 tar행동 을 원하기 때문에 .


3

오늘날 최적이 아닌 UI 일지 모르지만 디스크가 상당히 비쌀 때 UNIX를 디자인하는 동안 1970 년경 어느 정도 시간이 걸렸습니다. 수백만 개의 셸 스크립트가 그런 식으로 작동하는 데 달려 있으며 너무 늦어서 변경하기가 어렵습니다.

원래 디자인 정보는 이 기사 를 참조하십시오 .


3

-r플래그 의 분명한 장점은 소스 디렉토리에있는 cp * /target/dir모든 파일 만 대상 디렉토리 에 복사 할 수 있으며 그 안에 포함 된 모든 디렉토리를 생략 (경고는 없지만) 할 수 있다는 것입니다. cp -r * /target/dir하위 디렉토리를 포함하여 모든 것을 대신 복사합니다.


2

파일은 디렉토리 뿐만 아니라 파일 및 디렉토리cp 를 복사하기위한 명령 인 경우에만 필요합니다 .

디렉토리 사본에 대한 특수 명령이있는 경우 "기본"동작은 재귀 적 사본입니다.


1
맞는 말이다. 그러나 누군가 파일이 하나 이상없는 디렉토리를 복사하는 이유는 무엇입니까? 그렇다면 왜 그냥 사용하지 mkdir않습니까?
JakeGould

1
@JakeGould 소유권과 권한을 유지해야 할 수도 있기 때문에 어쩌면?
Ruslan

1

다른 사람들이 언급했듯이, 디렉토리는 기본적으로 다른 유형의 파일 (일반 파일과 달리)이며 일반적으로 다른 파일을 "포함"합니다. 하위 디렉토리를 포함 할 수 있으며 동일한 디렉토리가 적용됩니다 ...

따라서 디렉토리 (사용자 관점)를 복사하는 경우 실제로 많은 파일 (파일 시스템 관점) (일반 파일, 디렉토리 파일, 심볼릭 링크 등)을 복사하고 모든 디렉토리 파일에 대해 반복적으로 반복합니다. 방법. 디렉토리 복사는 정의 적으로 재귀 프로세스이므로 cp의 인수를 호출 --recursive합니다.

물론 사용자 환경에서 명령 바로 가기를 만드는 것은 매우 쉽습니다 (영구적으로 사용 가능하도록 .profile / .bashrc 파일에 넣습니다).

alias cpr='cp -r'

아니면 더 나은 :

alias cpa='cp -av'

이렇게하면 디렉토리를 사용하여 복사 할 수 있으며 복사되는 cpa dir1 copyDir1내용을 인쇄 할뿐만 아니라 파일 권한도 적용합니다.

그리고 누군가 cp가 이론적으로 소스 파일이 디렉토리라는 것을 감지하고 그것을 재귀 적으로 복사해야하는지 물어볼 수 있기 때문에 다음과 같은 간단한 제안이 있습니다.

cp()
{
    if [ ! -e "$1" ]; then
        echo missing source file
        return 1
    fi
    arg="-d --preserve=all -v"
    if [ -d "$1" ]; then
        read -p "Copy directory recursively? " -n 1 -r
        if [ "$REPLY" == "y" ]; then
            arg="$arg -r"
        fi
        echo
    fi
    /usr/bin/cp $arg "$@"
}

이것은 저렴한 CP 래퍼입니다. 항상 모든 메타 데이터를 보존합니다 (예 : 파일 수정 시간 복사, 심볼릭 링크 복사 등).

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