반응형

간단한 파일 탐색을 위한 스크립트를 작성해보았다.
막강한 명령어인 find를 기반으로 동작하고 몇가지 옵션을 간편하게 적용할 수 있도록 해둔 것으로 이해하면 좋을 것 같다.

사용은 아래와 같다. (script의 이름은 대충 finder라고 지어뒀으니 마음에 드는 이름으로 바꿔서 쓰시길)

./finder.sh 경로이름 -i include -i want -e exclude -e trash -f json -h -o result.txt

 

여러가지 옵션을 지원하는데 간단하게 설명해보자면

  • -i : include
    전체 경로에서 해당 키워드가 포함되는 라인만 출력 대상에 포함한다.
    해당 옵션은 복수 개를 사용할 수 있다.
    예를 들자면
    -i task -i net
    위와 같이 옵션을 설정한다면 경로 상 task 키워드와 net 키워드가 모두 포함된 줄을 출력 대상에 포함한다.

    (이 부분은 요구사항을 어떻게 정의하고 ux를 어떻게 제공할지에 따른 개발자 개인의 성향 차이가 있을 수 있다.
    여러 -i 옵션에 사용된 키워드 중 하나만 포함되도 출력되는 것을 원할 수도 있으나 원하는 파일을 찾는다는 기능에 집중해서 생각해보면 하나라도 포함되는 것을 출력하게 되면 그 결과가 집중되지 않고 발산될 수 있는 가능성이 있음을 알 수 있다. 따라서 모든 키워드가 포함되는것이 원하는 기능의 측면에서 더 적절할 것이라는 결론을 내릴 수 있었다.)
  • -e : exclude
    이 옵션은 말 그대로 제외하고자 하는 키워드를 설정하는 것이다.
    -i 옵션과 동일하게 복수개를 설정할 수 있지만 해당 옵션은 개별 적용이 됨을 이해해야 한다.
  • -h : 숨김 파일 포함
    해당 옵션을 명시적으로 설정하게 되면 숨김 파일을 출력 결과에 포함하게 된다. 기본값은 당연히 숨김 파일은 숨긴채로 결과를 출력한다.
  • -f : 출력 포맷 (json, plain)
    이 옵션은 많은 개선/발전이 필요하다. 솔직하게는 구색을 위해 끼워넣은 옵션이라고 보는 편이 좋다.
    각설하고 해당 옵션은 json 또는 plain 이라는 키워드를 값으로 받게 된다. plain은 find 를 해서 나온 결과와 동일하며 json은 결과물들을 json array 형태로 출력해준다. 계층적으로 표현해주기 위해서는 tree 명령어의 도움을 받을 수는 있으나 해당 패키지의 설치가 필요하기에 굳이 지원하지 않는 것으로 결정하였다. (해당 패키지 설치는 아주 쉬운 편이지만 본 블로그에서는 왠만해서는 그 어떤 의존성도 없는 스크립트들을 만들어볼 것이다.)
  • -o 결과물 저장
    출력 결과 내용을 파일로 저장하기 위한 옵션이다. 
#!/bin/bash

usage() {
  echo "Usage: $0 path [-i include]... [-e exclude]... [-o output] [-h] [-f format]"
  echo "Options:"
  echo "  path  The directory path to search in."
  echo "  -i    Include keyword in path (can be used multiple times)"
  echo "  -e    Exclude keyword from path (can be used multiple times)"
  echo "  -o    Output file path"
  echo "  -h    Search hidden files"
  echo "  -f    Output format: json or plain (default: plain)"
  exit 1
}

declare -a includes
declare -a excludes
output=""
hidden="false"
format="plain"

# Capture the search path first
path="$1"
shift

# If no path or it starts with '-', show usage
if [ -z "$path" ] || [[ "$path" == -* ]]; then
  usage
fi

while getopts "i:e:o:hf:" opt; do
  case $opt in
    i) includes+=("$OPTARG") ;;
    e) excludes+=("$OPTARG") ;;
    o) output="$OPTARG" ;;
    h) hidden="true" ;;
    f) format="$OPTARG" ;;
    \?) usage ;;
  esac
done

# Start constructing the find command
cmd="find '$path'"

# Handle hidden files
if [ "$hidden" != "true" ]; then
  cmd="$cmd ! -path '*/.*'"
fi

# Handle include keywords
if [ "${#includes[@]}" -gt 0 ]; then
  for keyword in "${includes[@]}"; do
    cmd="$cmd -path '*$keyword*'"
  done
fi

# Handle exclude keywords
for keyword in "${excludes[@]}"; do
  cmd="$cmd ! -path '*$keyword*'"
done

# Add the print command
cmd="$cmd -print"

# Handle format
case "$format" in
  json)
    cmd="$cmd | sed 's/^/\"/' | sed 's/$/\",/' | (echo '['; cat; echo ']')"
    ;;
  plain)
    ;; # Nothing to do here, as the default is to just print
  *)
    ;; # Default case: just print
esac

# Handle output
if [ -n "$output" ]; then
  cmd="$cmd > '$output'"
fi

eval "$cmd"

 

반응형

+ Recent posts