여러 파일의 문자열을 현재 하위 디렉터리 이름으로 변경

여러 파일의 문자열을 현재 하위 디렉터리 이름으로 변경

여러 개의 디렉터리가 있는데 각 디렉터리에는 다음 줄이 포함된 파일이 포함되어 있습니다.

../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>

이 변수에는 $epwdsed와 함께 사용할 수 있는 이스케이프된 디렉터리 이름이 포함되어 있습니다. 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 -unesed -ne

분석은 다음과 같습니다.

  1. 먼저 매개변수가 있습니다. 형식 문자열을 반복해서 사용하고 및를 다음과 같이 설정 하겠습니다 set.printf$PWD$OLDPWD.

  2. 다음으로 프로젝트 반복을 시작합니다.several directories. 이것이 실제 디렉토리이든 심볼릭 링크이든 우리는 -P물리적인 표준 경로 이름을 $PWDset습니다 $2.

  3. 다음에 일어날 일은 heredoc 리디렉션의 맨 아래에서 발생합니다. 쉘이 우리를 위해 보호하는 안전한 임시 파일에 paste모든 것을 읽어 들이고 ./infile각 줄 앞에 공백을 추가합니다. 그런 다음 쉘은 임시 파일을 stdin으로 설정하고 ./infile다시 할당하지만 이번에는 stdout으로 할당합니다.

  4. sed편집하는 경우는 드뭅니다. 일치하는 줄을 만나기 전에 각 줄의 첫 번째 문자를 제거하고 p결과를 인쇄합니다. 일단 라인을 만나면 q완전히 입력됩니다 - 아무것도 인쇄되지 않습니다.

  5. 그러나 stdout에 줄 바꿈이 뒤따라 printf인쇄되고 중단된 부분에서 stdin을 선택합니다.../${PWD##*/}_q[123].outcutsed(플레이라인 바로 뒤)각 입력 라인에서 첫 번째 바이트를 제거하면서 나머지를 읽습니다.

따라서 편집된 내용 전체가 ./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.ulrename

루프를 사용하여 디렉터리를 탐색합니다.

for d in */; do … done

rename각 디렉터리의 파일 이름을 바꾸기 위해 호출됩니다 .

for d in */; do
  rename /a_a "/${d%/}" "$d"a_a*
done

관련 정보