/
많은 디렉토리를 포함하는 디렉토리가 있고 /mydir
각 디렉토리는 비슷한 구조를 가져야 한다고 가정해 보겠습니다./hisdir
/herdir
각 디렉토리에는 디렉토리 와 그 안에 파일이 /
있어야 합니다 .doc
doc1.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
, elt2
는 elt3
배열의 요소입니다).
다음과 같이 할 수도 있습니다.
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
인용 부호특정 문자의 문제를 방지하는 단어입니다.
또는 :zsh
bash
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, 키 /를 사용하여 "출력 리디렉션"을 검색하세요.