디렉토리 트리를 통해 재귀 적으로 작업하고 각 파일에서 특정 명령을 실행하고 경로, 파일 이름, 확장명, 파일 크기 및 기타 특정 텍스트를 bash의 단일 파일로 출력하는 방법은 무엇입니까?
디렉토리 트리를 통해 재귀 적으로 작업하고 각 파일에서 특정 명령을 실행하고 경로, 파일 이름, 확장명, 파일 크기 및 기타 특정 텍스트를 bash의 단일 파일로 출력하는 방법은 무엇입니까?
답변:
find솔루션은 간단하고 강력 하지만 좀 더 복잡한 솔루션을 만들기로 결정했습니다 . 며칠 전에 보았던 이 흥미로운 기능을 기반으로 합니다 .
1. 라는 실행 스크립트 파일 작성 walk에 위치하고 있으며, /usr/local/bin쉘 명령과 액세스 할 수를 :
sudo touch /usr/local/bin/walk
sudo chmod +x /usr/local/bin/walk
sudo nano /usr/local/bin/walk
nano: Shift+ Insert붙여 넣기; Ctrl+ O그리고 Enter저장을 위해; Ctrl+ X종료합니다.2. 스크립트 내용 walk은 다음과 같습니다.
#!/bin/bash
# Colourise the output
RED='\033[0;31m' # Red
GRE='\033[0;32m' # Green
YEL='\033[1;33m' # Yellow
NCL='\033[0m' # No Color
file_specification() {
FILE_NAME="$(basename "${entry}")"
DIR="$(dirname "${entry}")"
NAME="${FILE_NAME%.*}"
EXT="${FILE_NAME##*.}"
SIZE="$(du -sh "${entry}" | cut -f1)"
printf "%*s${GRE}%s${NCL}\n" $((indent+4)) '' "${entry}"
printf "%*s\tFile name:\t${YEL}%s${NCL}\n" $((indent+4)) '' "$FILE_NAME"
printf "%*s\tDirectory:\t${YEL}%s${NCL}\n" $((indent+4)) '' "$DIR"
printf "%*s\tName only:\t${YEL}%s${NCL}\n" $((indent+4)) '' "$NAME"
printf "%*s\tExtension:\t${YEL}%s${NCL}\n" $((indent+4)) '' "$EXT"
printf "%*s\tFile size:\t${YEL}%s${NCL}\n" $((indent+4)) '' "$SIZE"
}
walk() {
local indent="${2:-0}"
printf "\n%*s${RED}%s${NCL}\n\n" "$indent" '' "$1"
# If the entry is a file do some operations
for entry in "$1"/*; do [[ -f "$entry" ]] && file_specification; done
# If the entry is a directory call walk() == create recursion
for entry in "$1"/*; do [[ -d "$entry" ]] && walk "$entry" $((indent+4)); done
}
# If the path is empty use the current, otherwise convert relative to absolute; Exec walk()
[[ -z "${1}" ]] && ABS_PATH="${PWD}" || cd "${1}" && ABS_PATH="${PWD}"
walk "${ABS_PATH}"
echo
3. 설명 :
이 walk()기능 의 주요 메커니즘은 Zanna의 대답 에 꽤 잘 설명되어 있습니다. 새로운 부분 만 설명하겠습니다.
walk()함수 내 에서이 루프를 추가했습니다.
for entry in "$1"/*; do [[ -f "$entry" ]] && file_specification; done
즉 $entry, 파일 인 각각에 대해 함수가 실행됩니다 file_specification().
이 기능 file_specification()에는 두 부분이 있습니다. 첫 번째 부분은 파일과 관련된 데이터 (이름, 경로, 크기 등)를 가져옵니다. 두 번째 부분은 올바른 형식의 데이터를 출력합니다. 데이터를 형식화하려면 명령이 사용됩니다 printf. 스크립트를 수정하려면 이 기사 와 같은 이 명령에 대해 읽어야 합니다.
이 기능 file_specification()은 각 파일에 대해 실행해야하는 특정 명령을 넣을 수있는 좋은 위치 입니다. 이 형식을 사용하십시오.
"$ {entry}" 명령
또는 명령의 출력을 변수로 저장 한 다음 printf이 변수 등을 저장할 수 있습니다 .
MY_VAR = "$ ( 명령 "$ {entry} ")"
printf "% * s \ t 파일 크기 : \ t $ {YEL} % s $ {NCL} \ n"$ ((indent + 4)) '' "$ MY_VAR"
또는 직접 printf명령의 출력 :
printf "% * s \ t 파일 크기 : \ t $ {YEL} % s $ {NCL} \ n"$ ((indent + 4)) '' "$ ( command "$ {entry} ")" 구걸 섹션 Colourise the output은 printf명령 내 에서 출력을 채색하기 위해 사용되는 몇 가지 변수를 초기화 합니다. 이에 대한 자세한 내용은 여기를 참조하십시오 .
스크립의 맨 아래에는 절대 및 상대 경로를 처리하는 추가 조건이 추가됩니다.
4. 사용 예 :
walk현재 디렉토리에 대해 실행하려면 다음 을 수행하십시오.
walk # You shouldn't use any argument,
walk ./ # but you can use also this formatwalk하위 디렉토리에 대해 실행하려면 다음 을 수행하십시오.
walk <directory name>
walk ./<directory name>
walk <directory name>/<sub directory>walk다른 디렉토리에 대해 실행하려면 다음 을 수행하십시오.
walk /full/path/to/<directory name>walk출력을 기반으로 텍스트 파일을 작성하려면 다음을 수행하십시오 .
walk > output.file색상 코드없이 출력 파일을 만들려면 ( source ) :
walk | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g" > output.file5. 사용 데모 :
아직 아무도 게시하지 않은 이유에 대해 약간 당황했지만 옵션을 사용하고 사용 bash하면 실제로 재귀 기능이 globstar있습니다.** glob . 따라서 다음과 같이 bash 재귀 globstar를 사용하는 (거의) 순수한 스크립트를 작성할 수 있습니다 .
#!/usr/bin/env bash
shopt -s globstar
for i in ./**/*
do
if [ -f "$i" ];
then
printf "Path: %s\n" "${i%/*}" # shortest suffix removal
printf "Filename: %s\n" "${i##*/}" # longest prefix removal
printf "Extension: %s\n" "${i##*.}"
printf "Filesize: %s\n" "$(du -b "$i" | awk '{print $1}')"
# some other command can go here
printf "\n\n"
fi
done
여기서 우리는 매개 변수 확장을 사용하여 원하는 파일 이름 부분을 가져오고 파일 크기를 가져오고를 사용하여 du출력을 정리 하는 것을 제외하고 외부 명령에 의존하지 않습니다 awk.
그리고 디렉토리 트리를 통과 할 때 출력은 다음과 같아야합니다.
Path: ./glibc/glibc-2.23/benchtests
Filename: sprintf-source.c
Extension: c
Filesize: 326
메이크업 확신이와 실행 가능 : 스크립트 사용의 표준 규칙이 적용 chmod +x ./myscript.sh과를 통해 현재 디렉토리에서 실행할 ./myscript.sh나에 배치 ~/bin하고 실행 source ~/.profile.
"$(file "$i")"(위의 스크립트에서 printf의 두 번째 부분으로) 반환 되는 MIME 정보를 정말로 원 하십니까?
output the path, filename, extension, filesize 했으므로 답변은 요청 된 내용과 일치합니다. :)
당신은 find일을 할 수 있습니다
find /path/ -type f -exec ls -alh {} \;
크기가있는 모든 파일을 나열하려는 경우 도움이됩니다.
-exec\;파일을 하나씩 구문 분석하는 데 사용되는 각 파일에 대해 사용자 정의 명령 또는 스크립트를 실행할
수 있습니다 +;. 파일을 연결하려는 경우 사용할 수 있습니다 (파일 이름을 의미 함).
와 함께 find.
find /path/ -type f -printf "path:%h fileName:%f size:%kKB Some Text\n" > to_single_file
또는 대신 아래를 사용할 수 있습니다.
find -type f -not -name "to_single_file" -execdir sh -c '
printf "%s %s %s %s Some Text\n" "$PWD" "${1#./}" "${1##*.}" $(stat -c %s "$1")
' _ {} \; > to_single_file
find -printf). +1
트리의 깊이를 알고 있다면 가장 쉬운 방법은 와일드 카드를 사용하는 것 *입니다.
쉘 스크립트 나 함수로하고 싶은 모든 것을 작성하십시오
function thing() { ... }
그런 다음 , ... 등 을 실행하십시오 for i in *; do thing "$i"; done.for i in */*; do thing "$i"; done
함수 / 스크립트 내에서 간단한 테스트 를 사용 하여 작업하려는 파일을 찾아 내고 필요한 작업을 수행 할 수 있습니다.
$i.
for i in */*작동 하는지 이해하지 못한다고 생각 합니다. for i in */*; do printf "|%s|\n" "$i"; done