한 번에 여러 하위 디렉터리 만들기

한 번에 여러 하위 디렉터리 만들기

/많은 디렉토리를 포함하는 디렉토리가 있고 /mydir각 디렉토리는 비슷한 구조를 가져야 한다고 가정해 보겠습니다./hisdir/herdir

각 디렉토리에는 디렉토리 와 그 안에 파일이 /있어야 합니다 .docdoc1.txt

사람들은 순진하게 자신이 수행할 수 있다고 생각할 수도 있습니다.

mkdir */doc
touch */doc/doc1.txt

그러나 그것은 잘못된 것입니다. 왜냐하면 그것은 와일드카드가 작동하는 방식이 아니기 때문입니다.

cp한 예제에서 구조체를 한 번만 만든 다음 다른 예제에 전달 하지 않고도 이 작업을 수행할 수 있는 방법이 있습니까 ?

그리고 그렇지 않은 경우 기존 파일을 덮어쓰지 않고 위의 해결 방법을 수행할 수 있는 방법이 있습니까( mydir보존하려는 일부 데이터가 있는 구조가 이미 포함되어 있다고 가정)?

편집: 가능하다면 스크립트 사용을 피하고 싶습니다.

답변1

Bash에서는 다음 줄과 같은 것을 사용하십시오.

mkdir -p {mydir,hisdir,herdir}/doc
touch {mydir,hisdir,herdir}/doc/doc1.txt

{...}구문을 "대괄호 확장"이라고 하며 다음과 동일합니다.경로명 확장, 여기서 파일 이름은 반드시 존재해야 하며 생성된 결과는 이미 존재하는 것과 일치할 필요가 없습니다. 이러한 -p방법은 필요에 따라 경로의 모든 중첩 구성 요소를 생성합니다. 그렇지 않으면 mkdir이 상위 디렉터리 앞에 최종 "doc" 디렉터리를 생성하려고 시도할 때 오류가 발생합니다.

(예를 보려면 bash 매뉴얼 페이지를 확인하십시오. 이와 같은 하위 디렉토리를 만드는 것이 일반적인 사용 사례입니다.)

mydir, hisdor 및 herdir이 이미 존재하고 이를 다시 입력하고 싶지 않다면 Stéphane Chazelas의 솔루션이 아마도 가장 똑똑할 것입니다. 그러나 항상 그렇게 하지 않는 한 스마트가 항상 최선은 아닙니다. bash 배열 확장이 꺼져 있다는 것을 기억할 수 없습니다. 커프와 나는 많은 하급 시스템 관리자가 그것을 인식하지 못할 것이라고 확신합니다. 이 경우 find다음과 같이 루프 또는 를 사용하는 것이 좋습니다 .

find . -maxdepth 1 -mindepth 1 -type d \
   -execdir mkdir {}/doc \; -execdir touch {}/doc/doc1.txt \;

그러나 실제로 간단한 루프의 장점은 간단하고 더 이상 입력이 필요하지 않다는 것입니다!

답변2

그리고 zsh:

dirs=(*(/))
mkdir -- $^dirs/doc
touch -- $^dirs/doc/doc1.txt

(/)와일드카드 한정자, /선택 디렉토리만 의미합니다.

$^array(연산자를 연상시키는 rc) ^은 배열에서 괄호를 여는 유형의 확장이므로 $^array/doc( {elt1,elt2,elt3}/doc여기서 elt1, elt2elt3배열의 요소입니다).

다음과 같이 할 수도 있습니다.

mkdir -- *(/e:REPLY+=/doc:)
touch -- */doc(/e:REPLY+=/doc1.txt:)

e선택할 파일에 대해 특정 코드를 실행하는 또 다른 전역 한정자는 어디에 있습니까 ?

그리고 rc/ es/ akanga:

dirs = */
mkdir -- $dirs^doc
touch -- $dirs^doc/doc1.txt

^이는 향상된 연결 연산자와 유사한 연산자를 사용합니다 .

rc지원하지 않음와일드카드 한정자(이것은 zsh 전용 기능입니다). */모든 디렉토리로 확장및 디렉토리 심볼릭 링크, 그리고 /첨부되었습니다.

그리고 tcsh:

set dirs = */
mkdir -- $dirs:gs:/:/doc::q
touch -- $dirs:gs:/:/doc/doc1.txt::q

이는 :x변수 확장에도 적용할 수 있는 히스토리 수정자입니다. :gs글로벌 대안입니다.:q 인용 부호특정 문자의 문제를 방지하는 단어입니다.

또는 :zshbash

dirs=(*/)
mkdir -- "${dirs[@]/%/doc}"
touch -- "${dirs[@]/%/doc/doc1.txt}"

${var/pattern/replace}Korn 쉘의 대체 연산자와 유사합니다. 의 경우 ${array[@]/pattern/replace}배열의 각 요소에 적용됩니다. %이것은 의미한다마지막에.

다양한 고려 사항:

dirs=(*/)[ -L "$file" ]디렉토리와 디렉토리에 대한 심볼릭 링크를 포함합니다(루프에서 사용되는 경우를 제외하고는 심볼릭 링크를 제외할 수 있는 방법이 없습니다). 반면 dir=(*(/))(zsh 확장자)는 디렉토리만 포함합니다( dir=(*(-/))후행 슬래시를 추가하지 않고 디렉토리에 대한 심볼릭 링크 포함).

숨겨진 디렉터리는 제외됩니다. 각 셸에는 숨겨진 파일을 포함하기 위한 특정 옵션이 있습니다.

현재 디렉터리에 다른 사람이 쓸 수 있는 경우 보안 문제가 발생할 수 있습니다. 사람들이 거기에 심볼릭 링크를 만들어서 원하지 않는 디렉토리나 파일을 만들 수 있기 때문입니다. 심볼릭 링크를 고려하지 않는 솔루션을 사용하더라도 dirs=(*/)디렉토리를 과 사이의 심볼릭 링크로 대체할 수 있기 때문에 여전히 경쟁 조건이 있습니다 mkdir....

답변3

for d in /*/
do  [ -d "$d" ] || break
    f=$d/docs/doc1.txt    
    mkdir -p -- "${f%/*}"
    touch -- "$f"
done

나는 그것이 당신의 목표에 적합하다고 생각합니다. 어쩌면 내가 뭔가를 놓친 것 같습니다.

그렇지 않으면 다음을 수행할 수 있습니다.

set -- /*/
[ -d "$1" ] && 
printf 'd=$%d
    mkdir -p -- "$d/docs" && 
    touch -- "$d/docs/doc1.txt"
' $(seq "$#") | sh -s -- "$@"

또는:

set -- /*/
while [ -d "$1" ] 
do  mkdir -p -- "$1"/docs
    touch -- "$1"/docs/doc1.txt
shift ; done

답변4

알았어, 그렇게 해보자짧은:

ls -1|xargs -i% bash -c 'mkdir %/doc;>>%/doc/doc1.txt'


- 우리는 당신과 같은 디렉토리에 있습니다시작 디렉토리.

  • ls -1목록 1개herdir 등, 한 줄에 하나씩(다른 것은 없음)

  • xarg스크립트 인수를 사용하여 셸을 실행하고 %를 디렉터리로 바꿉니다.

  • 각 디렉터리에 대해 다음을 수행합니다.

    • bash두 개의 명령을 포함하는 하나의 문자열 인수를 사용하여 쉘 스크립트로 실행하십시오.

      • mkdir %/doc디렉터리 생성
      • >>%/doc/doc1.txt빈 파일 생성 2


$ ls
$ mkdir mydir hisdir herdir
$ ls                       
herdir  hisdir  mydir
$ ls -1|xargs -i% bash -c 'mkdir %/doc;>>%/doc/doc1.txt'
$ find
.
./herdir
./herdir/doc
./herdir/doc/doc1.txt
./hisdir
./hisdir/doc
./hisdir/doc/doc1.txt
./mydir
./mydir/doc
./mydir/doc/doc1.txt



1) 예술적 자유;찾다. -최대 깊이 1 -유형 d

2) >>file여기에 touch와 유사하게 빈 파일을 만듭니다. 자세한 내용은 bash다음을 참조 하세요.man bash, 키 /를 사용하여 "출력 리디렉션"을 검색하세요.

관련 정보