dataindex 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. #!/bin/sh
  2. usage () {
  3. cat <<EOF>&2
  4. Usage: ${0##*/} [OPTIONS] FOLDERS
  5. Output index of folder hierarchies to stdout. This is used as a small "backup"
  6. purpose. In case of data loss, it is still possible to get the full file list
  7. thanks to the indexes.
  8. Version control and encfs-encrypted folders are skipped.
  9. Options:
  10. -f: When outputting to a file, overwrite if it exists.
  11. -w: Output each index to individual files in current folder. It uses the folder
  12. name as basename.
  13. EOF
  14. }
  15. opt_noclobber=true
  16. opt_file=false
  17. while getopts ":fhw" opt; do
  18. case $opt in
  19. f)
  20. opt_noclobber=false ;;
  21. h)
  22. usage
  23. exit ;;
  24. w)
  25. opt_file=true ;;
  26. \?)
  27. usage
  28. exit 1 ;;
  29. esac
  30. done
  31. shift $((OPTIND - 1))
  32. if [ $# -eq 0 ]; then
  33. usage
  34. exit 1
  35. fi
  36. ## 'realpath' is required in case argument is ending with '.' or '..'.
  37. if ! command -v realpath >/dev/null 2>&1; then
  38. echo >&2 "'realpath' not found"
  39. exit 1
  40. fi
  41. for i ; do
  42. [ ! -d "$i" ] && continue
  43. [ -e "$i"/.encfs*.xml ] && continue
  44. ## We strip "./" from find's listing since we don't need it. We could avoid
  45. ## printing it in the first place, but there are several shortcomings:
  46. ## - Find over '.*' and '*', is bad practice since if will fail on
  47. ## non-existing files or for files beginning with a dash.
  48. ## - The 'printf' command in find is for GNU find only.
  49. ## 'LC_ALL=C sort' is required to make sure to output is consistent across
  50. ## different systems.
  51. echo >&2 "$i"
  52. ## The two following lines do the same for the same time cost. The former is shorter.
  53. # find "$i" -type f | awk -v str="$i" '{l=length(str)+2; print substr($0, l)}' | LC_ALL=C sort > "$OUTPUT"
  54. (cd -- "$i" && find . \( -path '*.git*' -o -path '*.svn*' -o -path '*.hg*' \) -prune -o -type f) | sed 's/^.\///' | LC_ALL=C sort | \
  55. if $opt_file; then
  56. i="$(realpath -- "$i")"
  57. base="${i##*/}"
  58. output="$base.index"
  59. [ -e "$output" ] && $opt_noclobber && output="$base-$(date +%F-%T).index"
  60. echo "$output"
  61. cat > "$output"
  62. else
  63. cat
  64. fi
  65. done