일련의 디렉토리를 한 번에 푸시하는 방법은 무엇입니까?

일련의 디렉토리를 한 번에 푸시하는 방법은 무엇입니까?

foo나는 하위 디렉터리를 포함하는 디렉터리에 있고 bar1 bar2그게 bar3전부입니다.

pushd, 및 을 foo하나 의 명령으로 실행하고 싶지만 멈췄습니다 .bar1bar2bar3

find `pwd` | xargs pushd

반품

xargs: pushd: No such file or directory

이 문제를 회피하기 위해 while 루프를 사용해 보았습니다.

find `pwd` | while read line ; do pushd $line ; done

그러면 올바르게 보이는 출력이 제공됩니다.

~/foo ~/foo
~/foo/bar1 ~/foo ~/foo
~/foo/bar2 ~/foo/bar1 ~/foo ~/foo
~/foo/bar3 ~/foo/bar2 ~/foo/bar1 ~/foo ~/foo

그러나 나중에 이것을 사용하면 dirs스택에 새 디렉터리를 추가하지 않았음을 알 수 있습니다.

~/foo

내가 뭘 잘못하고 있는지 알아낼 수 있는 사람이 있나요?

답변1

당신은 매우 가깝습니다. 너가 원하는 것을 할수있어

while read line; do pushd "$line"; done < <(find "$(pwd)" -type d)

명령의 문제점은 유용하려면 기본(상위) 프로세스에서 pushd수행 cd되어야 하며(시스템 설정 방법에 따라 약간의 차이가 있음) 파이프라인의 명령이 하위 프로세스(하위 프로세스)에서 실행된다는 것입니다. ). 파이프를 주지 않고 마법처럼 파이프를 줍니다.< <(cmd)

POSIX는 .<(cmd)

불행하게도 이 xargs접근 방식은 실패할 운명입니다. 왜냐하면 pushd(like cd)는 쉘 내장(즉,프로그램pushd) 이라고 하며 xargs외부 실행 프로그램이 필요합니다. 다음을 사용하여 (거의) 올바르게 보이는 출력을 얻을 수 있습니다.

$ find "$(pwd)" -type d | xargs -i sh -c 'pushd "$1"' sh
~/foo ~/foo
~/foo/bar1 ~/foo
~/foo/bar2 ~/foo
~/foo/bar3 ~/foo

그러나 이것은 쉘을 외부 프로그램으로 실행하고 각 디렉토리에 대해 (독립적으로) 이 작업을 수행합니다. 이것은 다소 가깝습니다.

$ find "$(pwd)" -type d | xargs sh -c 'for line do pushd "$line"; done' sh
~/foo ~/foo
~/foo/bar1 ~/foo ~/foo
~/foo/bar2 ~/foo/bar1 ~/foo ~/foo
~/foo/bar3 ~/foo/bar2 ~/foo/bar1 ~/foo ~/foo

단일 셸 프로세스를 실행하고 모든 디렉터리를 반복하도록 지시합니다. 보시다시피 이 기술은 두 번째 시도(및 내 답변)와 유사하며 결과는 두 번째 시도와 동일합니다. pushd네 번 호출되는 새로운 셸 프로세스를 얻고 결국 A 디렉터리 스택이 생성됩니다. 즉, 5개 레벨 깊이(시작 디렉토리를 두 ​​번 계산) - 그러나 새 셸 프로세스는 하위 프로세스에 있으며 다음 셸 프롬프트가 표시되면저것쉘 프로세스가 사라졌습니다.

참고로 명령은 다음과 다소 유사합니다. 내가 몇 년 전에 했던 대답은스티븐 차제라스명령 구조 논의 sh -c long_complex_shell_command sh여기그리고여기.

답변2

이것은 직업이 아닙니다 find.

for subdirectory in */; do
  pushd -- "$subdirectory"
done

pushd예를 들어 cd영향을 미치려는 셸 환경에서 코드를 실행해야 하기 때문에 코드가 작동하지 않습니다 . pushd외부 명령 은 의미가 없기 때문에 호출할 수 있는 xargs외부 명령이 없습니다. 아무 영향도 미치지 않습니다. 파이프의 오른쪽은 하위 ​​쉘에서 실행됩니다(쉘 내부에는 다른 쉘에서 실행되는 일부 쉘이 있으며 두 번째 시도는 작동함을 볼 수 있습니다) pushd.

find `pwd` | {
  while read line ; do pushd $line ; done;
  dirs
}

디렉터리 이름에 특수 문자가 포함되어 있지 않으면 유효합니다.변수 대체를 제거해야 하는 이유를 알지 못하는 한 항상 변수 대체 주위에 큰따옴표를 넣으십시오..

관련 정보