여러 개의 디렉터리가 있는데 각 디렉터리에는 다음 줄이 포함된 파일이 포함되어 있습니다.
../a_a_q1.out ../a_a_q2.out ../a_a_q3.out
a_a
모든 하위 디렉터리를 반복하고 해당 섹션을 현재 하위 디렉터리 이름으로 변경하고 싶습니다 . 예를 들어 하위 디렉터리가 이라고 하면 awesome_directory
다음 줄을 읽어야 합니다.
../awesome_directory_q1.out ../awesome_directory_q2.out ../awesome_directory_q3.out
어떻게 이를 달성할 수 있나요?
하위 디렉터리 이름만 사용하고 싶습니다. 예를 들어 awesome_directory
전체 거래( //something/server/user/other_stuff/more/awesome_directory
) 대신 ( ) 부분만 필요합니다.
답변1
Bash의 두 단계에는 다음과 같은 한 가지 방법이 있습니다.
epwd=$(basename `pwd`)
sed -i "s/a_a/$epwd/g" <filename>
이 변수에는 $epwd
sed와 함께 사용할 수 있는 이스케이프된 디렉터리 이름이 포함되어 있습니다. sed 명령은 a_a의 모든 발생을 작업 디렉토리로 바꿉니다.
편집: 원래 답변의 첫 번째 줄은 전체 경로가 아닌 현재 디렉터리 이름만 포함하도록 편집되었습니다. 전체 경로를 사용하려면
epwd=$(pwd|sed 's/\//\\\//g')
답변2
지금까지 나는 이것을 생각해 냈습니다.
var=("${PWD##*/}")
sed -i "s/a_a/$var/g" filename
답변3
set '%s_q1.out %s_q2.out %s_q3.out\n'
:|for d in several directories
do cd -P -- "$d" || ! break
set "$1" "../${PWD##*/}"
{ sed -ne'\|\( \.\./a_a_q[123]\.out\)\{3\}|q;s/.//p'
printf "$@" "$2" "$2"; cut -c2-
} <<-IN >./infile
$(paste -d\ - ./infile)
IN
done
sed
이는 POSIX 및 bash
, zsh
, , ksh
, mksh
쉘 등과 함께 작동합니다 . dash
또는 쉘을 사용할 때 여기에 있는 문서가 일반 파일에서 지원될 가능성이 낮으므로 공유 입력을 지원하는 데 필요한 기능 yash
에 의존할 수 없습니다 . lseek()
이러한 경우에는 위의 셸 중 하나로 전환해야 합니다.
GNU 를 사용한다면 sed
그냥 .sed -une
sed -ne
분석은 다음과 같습니다.
먼저 매개변수가 있습니다. 형식 문자열을 반복해서 사용하고 및를 다음과 같이 설정 하겠습니다
set
.printf
$PWD
$OLDPWD
.
다음으로 프로젝트 반복을 시작합니다.
several directories
. 이것이 실제 디렉토리이든 심볼릭 링크이든 우리는-P
물리적인 표준 경로 이름을$PWD
얻set
습니다$2
.다음에 일어날 일은 heredoc 리디렉션의 맨 아래에서 발생합니다. 쉘이 우리를 위해 보호하는 안전한 임시 파일에
paste
모든 것을 읽어 들이고./infile
각 줄 앞에 공백을 추가합니다. 그런 다음 쉘은 임시 파일을 stdin으로 설정하고./infile
다시 할당하지만 이번에는 stdout으로 할당합니다.sed
편집하는 경우는 드뭅니다. 일치하는 줄을 만나기 전에 각 줄의 첫 번째 문자를 제거하고p
결과를 인쇄합니다. 일단 라인을 만나면q
완전히 입력됩니다 - 아무것도 인쇄되지 않습니다.그러나 stdout에 줄 바꿈이 뒤따라
printf
인쇄되고 중단된 부분에서 stdin을 선택합니다.../${PWD##*/}_q[123].out
cut
sed
(플레이라인 바로 뒤)각 입력 라인에서 첫 번째 바이트를 제거하면서 나머지를 읽습니다.
따라서 편집된 내용 전체가 ./infile
이전 위치로 되돌아갑니다.
아, 테스트해봤습니다.
나는 변했다several directories
경로 이름을 일부 변경했으며 /tmp
...
{ seq 7
echo '../a_a_q1.out ../a_a_q2.out ../a_a_q3.out'
seq 9 14
printf %s\\n '' '' ''
} >/tmp/infile
...하나 썼다/tmp/infile
다음과 같이 보입니다:
1 2 삼 4 5 6 7 ../a_a_q1.out ../a_a_q2.out ../a_a_q3.out 9 10 11 12 13 14
그러나 위의 코드 조각을 실행한 후 /tmp
...
cat /tmp/infile
1 2 삼 4 5 6 7 ../tmp_q1.out ../tmp_q2.out ../tmp_q3.out 9 10 11 12 13 14
답변4
해당 a_a
부분이 일정하고 Linux를 실행 중인 경우 이 rename
유틸리티를 사용할 수 있습니다. Debian 및 그 파생 제품에서는 명령이 작업을 수행하지만 구문이 다른 다른 유틸리티이기 때문에 rename
로 변경합니다.rename.ul
rename
루프를 사용하여 디렉터리를 탐색합니다.
for d in */; do … done
rename
각 디렉터리의 파일 이름을 바꾸기 위해 호출됩니다 .
for d in */; do
rename /a_a "/${d%/}" "$d"a_a*
done