내 질문은 -r
디렉토리의 사본을 만들 때 (재귀) 플래그 를 사용해야하는 이유는 무엇입니까? 즉, 왜 이렇게 :
$ cp -r dir1 copyDir1
디렉토리를 복사 할 때이 동작을 원하지 않는 경우는 언제입니까?
디렉토리의 재귀 복사본이 실제로 "기본"동작이 아닙니 다. 우리가 항상 원하는 행동?
이것이 불필요한 플래그 인 것 같습니다.
내 질문은 -r
디렉토리의 사본을 만들 때 (재귀) 플래그 를 사용해야하는 이유는 무엇입니까? 즉, 왜 이렇게 :
$ cp -r dir1 copyDir1
디렉토리를 복사 할 때이 동작을 원하지 않는 경우는 언제입니까?
디렉토리의 재귀 복사본이 실제로 "기본"동작이 아닙니 다. 우리가 항상 원하는 행동?
이것이 불필요한 플래그 인 것 같습니다.
답변:
파일 시스템이 작동하는 방식에서 디렉토리는 실제로 파일을 포함하는 폴더가 아니라 디렉토리에 연결된 "하위"파일에 대한 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 항목이있는 파일 인 경우 해당 파일의 직선 사본을 만드는 것은 하드 링크의 작동 방식과 동일합니다. 어느 누구도 원하는 것이 아닙니다.
cp -r /bin
로 cp-r ~/bin
. 깃발 자체는 실수를 막거나 반드시주의를 기울이는 사람을 만들지 않습니다. 실수를 방지하려면 cp 명령을 사용하여 문제의 노드를 쉽게 확인하고 "이 디렉토리입니다. 모든 내용을 지정된 위치에 복사 하시겠습니까? /엔)?" 즉 것 안전망 . 디렉토리에 -r을 요구하면 무엇보다 많은 코드가 줄어 듭니다.
이것이 우리가 거의 항상 원하는 행동이라는 것은 매우 사실입니다. 그러나 이것이 반드시 재귀 적으로 복사하는 것이 기본 행동이어야한다는 것을 의미하지는 않습니다.
나는 그 이유 cp
가 유닉스 철학에 뿌리를 둔 것처럼 행동 한다고 생각 한다 . 유닉스 는 인터페이스와 구현 모두에서 간단한 프로그램뿐만 아니라 한 가지 일을 잘 수행하는 프로그램을 선호한다 (때로는 더 나쁘다 라고 함 ).
여기서 퍼즐의 핵심 부분은 cp
디렉토리를 복사하지 않고 cp
파일 (및 파일 만 )을 복사 한다는 것을 깨닫고 있습니다. 디렉토리 를 복사하려면 각 디렉토리의 파일을 복사하기 위해 cp
재귀 적으로 호출합니다 .
물론, "디렉토리 복사"와 "재귀 적으로 파일 복사"의 차이점은 사용자 관점에서 볼 때 전혀 아무것도 아니지만 이 인터페이스를 사용하면 구현이 단순하게 유지 됩니다.
cp
디렉토리를 복사 할 수있게 되면 곧 디렉토리에만 적합한 기능을 더 추가하려고합니다. 예를 들어로 끝나는 파일 이름 만 복사 할 수 있습니다 .sh
. 필연적으로는이 리드 팽창 과 기능 크리프 우리는 다른 운영 체제에서 사용되는 - 제작 소프트웨어가 느리고, 복잡하고 오류가 발생하기 쉬운.
또 다른 장점은 -r
인터페이스 아래에서 실제로 발생하는 상황을 사용자가 이해하는 데 도움 이된다는 것입니다. 이것의 좋은 부작용은 재귀 작업의 개념을 배우면 그것을 지원하는 다른 도구에 대해 배울 때 약간의 작업이 필요하다는 것입니다 (예 : 등 grep
)
어떤 사람들은 구현 세부 사항을 사용자에게 노출하는 것이 좋지 않으며 더 많은 기능을 갖는 것이 좋다고 확실히 말할 것입니다 . 여기서 나의 의도는 단지이 행동의 이론적 근거를 설명하는 것일 뿐이므로 어느 쪽이든 논쟁하려고하지 않습니다.
디렉토리와의 상호 작용을 통해 단일 파일이 아닌 디렉토리와 상호 작용하고 있음을 알 수 있습니다.
예를 들어 :
$ 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
기본값을 변경하면 수천 개의 쉘 스크립트가 중단됩니다. 이는 잘 알려진 기본 동작에 대한 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
행동 을 원하기 때문에 .
다른 사람들이 언급했듯이, 디렉토리는 기본적으로 다른 유형의 파일 (일반 파일과 달리)이며 일반적으로 다른 파일을 "포함"합니다. 하위 디렉토리를 포함 할 수 있으며 동일한 디렉토리가 적용됩니다 ...
따라서 디렉토리 (사용자 관점)를 복사하는 경우 실제로 많은 파일 (파일 시스템 관점) (일반 파일, 디렉토리 파일, 심볼릭 링크 등)을 복사하고 모든 디렉토리 파일에 대해 반복적으로 반복합니다. 방법. 디렉토리 복사는 정의 적으로 재귀 프로세스이므로 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 래퍼입니다. 항상 모든 메타 데이터를 보존합니다 (예 : 파일 수정 시간 복사, 심볼릭 링크 복사 등).