재귀적 찾기/바꾸기(디렉터리 깊이 고려)

재귀적 찾기/바꾸기(디렉터리 깊이 고려)

나는 기본적인 찾기/바꾸기를 통해 행운을 누렸습니다.

find . -name "*.php" -exec sed -i -e "s/<?php include 'http:\/\/www/<?php include '..\//g" \{\} \;

비슷한 결과를 얻을 수 있는 방법이 있는지 궁금합니다. 하지만 현재 디렉터리의 "깊이"를 고려하고 ../구조의 각 수준에 대한 대체 문자열 앞에 추가를 추가합니까?

답변1

다음과 같이 시도해 볼 수 있습니다.

find . -name '*.php' -exec sh -c \
'PREFIX=${1//[!/]/}; PREFIX=${PREFIX//\//..\/}; ...' sh {} \;

발견된 파일이 이면 으로 설정됩니다 PREFIX. 그런 다음 쉘 변수를 사용하여 해당 위치에 명령을 삽입할 수 있습니다.../dir/filenamesed...$PREFIX

이를 위해서는 ${var//find/repl}확장된 기능을 갖춘 쉘이 필요합니다. 이는 POSIX에서 지정되지 않았지만 Bash일부 POSIX 구현에는 ash지정되어 있습니다. 그렇지 않은 경우 접두사를 수행하려면 다른 것을 사용해야 합니다. 이 경우 단일 awk프로세스를 사용하여 해당 절에서 접두사 작업을 수행한 다음 (별도의 프로세스 BEGIN대신) 파일의 각 줄에서 교체를 수행합니다 .sed

답변2

사이트 루트와 관련된 디렉터리 깊이에 의존하는 기본 URL을 강제로 적용하는 유사한 작업이 있었습니다.

전체 솔루션은 아래에 게시되어 있습니다. @dubiousjim의 답변을 기반으로 하지만 인용 문제를 피하기 위해 쉘 기능을 사용하여 약간 다른 접근 방식을 취합니다.

fixlinks() {
  # strip the first level depth as we don't need it
  BASE=${1/#\.\//}
  # leave only one slash char for each nested dir
  BASE=${BASE//[!\/]/}
  # replace each / with ../ (escaped to ..\/ to be used as sed replacement part)
  BASE=${BASE//\//..\\\/} 
  if [[ $BASE ]]; then
    # enable debug mode
    set -x
    # add <base> tag leading to site root after <head> for each nested file
    sed -E -i "s/<head>\r?$/<head><base href=\"$BASE\"\/>/g" "$1"
    # silently disable debug mode
    { set +x; } 2>/dev/null
  fi
}
# iterate over all files from the site root
find . -name '*.html' | while read file; do fixlinks "$file"; done

관련 정보