Tools added
This commit is contained in:
commit
930d282ccc
2 changed files with 181 additions and 0 deletions
125
flac2m4a
Normal file
125
flac2m4a
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
#!/usr/bin/env bash
|
||||
# -----------------------------------------------------------------------------
|
||||
# Title: flac2m4a
|
||||
# Purpose: Comprehensive flac to m4a auto-converter
|
||||
# Version: 1.0.0
|
||||
# Developer: h@x
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
set -euo pipefail
|
||||
trap 'echo "✗ ERROR on line $LINENO (exit code $?): ${BASH_COMMAND}" >&2' ERR
|
||||
IFS=$'\n\t'
|
||||
|
||||
# === Input & output directories ===
|
||||
SRC_DIR="${1:-.}"
|
||||
DST_DIR="${2:-./m4a_output}"
|
||||
[[ -d "$SRC_DIR" ]] || {
|
||||
echo "ERROR: Source directory '$SRC_DIR' not found." >&2
|
||||
exit 1
|
||||
}
|
||||
mkdir -p "$DST_DIR"
|
||||
|
||||
# === FFmpeg capability check ===
|
||||
if ! ffmpeg -hide_banner -muxers 2>/dev/null | grep -qw mov; then
|
||||
echo "ERROR: FFmpeg build lacks the MP4/mov muxer required for .m4a outputs." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# === Codec selection ===
|
||||
declare -a CODEC_OPTS
|
||||
if ffmpeg -hide_banner -encoders 2>/dev/null | grep -qw libfdk_aac; then
|
||||
CODEC_OPTS=( -c:a libfdk_aac -profile:a aac_he_v2 -cutoff 18000 -b:a 256k )
|
||||
echo "INFO: Using libfdk_aac HE-AAC v2 @256 kbps." >&2
|
||||
else
|
||||
CODEC_OPTS=( -c:a aac -b:a 256k )
|
||||
echo "WARNING: Falling back to native AAC @256 kbps." >&2
|
||||
fi
|
||||
|
||||
declare -a META_OPTS=(
|
||||
-map_metadata 0
|
||||
-id3v2_version 3
|
||||
-write_id3v1 1
|
||||
-metadata:s:a encoder="ffmpeg/${CODEC_OPTS[1]}"
|
||||
)
|
||||
declare -a FFMPEG_OPTS=( -hide_banner -loglevel error -nostdin -n )
|
||||
|
||||
# === Discover .flac files ===
|
||||
mapfile -d '' files < <(find "$SRC_DIR" -type f -iname '*.flac' -print0)
|
||||
TOTAL=${#files[@]}
|
||||
|
||||
(( TOTAL > 0 )) || {
|
||||
echo "Nothing to do: no .flac files found under '$SRC_DIR'." >&2
|
||||
exit 0
|
||||
}
|
||||
echo "FOUND: $TOTAL .flac file(s) to process." >&2
|
||||
|
||||
# === Progress-bar initialization ===
|
||||
BAR_WIDTH=40
|
||||
COUNT=0
|
||||
LAST_PCT=-1
|
||||
|
||||
# pre-fill bar with dots, print initial line
|
||||
empty_bar=$(printf '%*s' "$BAR_WIDTH" '' | tr ' ' '.')
|
||||
printf "Progress: [%-${BAR_WIDTH}s] 0%% (%d/%d)\n" \
|
||||
"$empty_bar" 0 "$TOTAL" >&2
|
||||
|
||||
# === Conversion loop with ANSI overwrite ===
|
||||
##declare -a SKIPPED CONVERTED
|
||||
##declare -A FAILED
|
||||
|
||||
declare -a SKIPPED=()
|
||||
declare -a CONVERTED=()
|
||||
declare -A FAILED=()
|
||||
|
||||
for SRC_FILE in "${files[@]}"; do
|
||||
(( COUNT += 1 ))
|
||||
REL_PATH="${SRC_FILE#"$SRC_DIR"/}"
|
||||
DST_FILE="$DST_DIR/${REL_PATH%.flac}.m4a"
|
||||
mkdir -p "$(dirname "$DST_FILE")"
|
||||
|
||||
# calculate and render updated bar if % changed
|
||||
PCT=$(( COUNT * 100 / TOTAL ))
|
||||
if (( PCT != LAST_PCT )); then
|
||||
LAST_PCT=$PCT
|
||||
filled=$(( COUNT * BAR_WIDTH / TOTAL ))
|
||||
fbar=$(printf '%*s' "$filled" '' | tr ' ' '#')
|
||||
ebar=$(printf '%*s' "$(( BAR_WIDTH - filled ))" '' | tr ' ' '.')
|
||||
# move cursor up one line, carriage-return, then overwrite
|
||||
printf "\033[1A\rProgress: [%s%s] %3d%% (%d/%d)\n" \
|
||||
"$fbar" "$ebar" "$PCT" "$COUNT" "$TOTAL" >&2
|
||||
fi
|
||||
|
||||
# skip or convert
|
||||
if [[ -f "$DST_FILE" ]]; then
|
||||
SKIPPED+=("$REL_PATH")
|
||||
else
|
||||
if ffmpeg "${FFMPEG_OPTS[@]}" -i "$SRC_FILE" \
|
||||
"${CODEC_OPTS[@]}" -vn "${META_OPTS[@]}" -f ipod "$DST_FILE"; then
|
||||
CONVERTED+=("$REL_PATH")
|
||||
else
|
||||
FAILED["$REL_PATH"]=1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# === Summary ===
|
||||
echo >&2
|
||||
printf "========== SUMMARY ==========\n" >&2
|
||||
|
||||
printf "Skipped (already present): %d\n" "${#SKIPPED[@]}" >&2
|
||||
for f in "${SKIPPED[@]}"; do printf " • %s\n" "$f"; done >&2
|
||||
|
||||
echo >&2
|
||||
printf "Converted: %d\n" "${#CONVERTED[@]}" >&2
|
||||
for f in "${CONVERTED[@]}"; do printf " • %s\n" "$f"; done >&2
|
||||
|
||||
echo >&2
|
||||
printf "Failed: %d\n" "${#FAILED[@]}" >&2
|
||||
for f in "${!FAILED[@]}"; do printf " • %s\n" "$f"; done >&2
|
||||
|
||||
echo >&2
|
||||
printf "Output directory: '%s'\n" "$DST_DIR" >&2
|
||||
echo "=============================" >&2
|
||||
|
||||
# appropriate exit code
|
||||
(( ${#FAILED[@]} )) && exit 2 || exit 0
|
||||
56
typechecker
Normal file
56
typechecker
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
#!/usr/bin/env bash
|
||||
# -----------------------------------------------------------------------------
|
||||
# Title: audit-dir-content.sh
|
||||
# Purpose: Comprehensive inventory of file types and subdirectory sizes
|
||||
# Version: 1.0.0
|
||||
# Developer: h@x
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
set -euo pipefail
|
||||
IFS=$'\n\t'
|
||||
|
||||
WORKDIR="${PWD##*/}"
|
||||
echo "=== typecheck - Check your folders for filetypes v1.1 ==="
|
||||
echo
|
||||
echo "=== Inventory for: ${WORKDIR} ==="
|
||||
echo
|
||||
|
||||
## 1) FILE-TYPE COUNTS
|
||||
echo ">> File-type breakdown (MIME) with counts"
|
||||
# Gather MIME types for all regular files at depth=1
|
||||
mapfile -t mime_types < <(
|
||||
find . -maxdepth 1 -type f -exec file --mime-type --brief {} + 2>/dev/null
|
||||
)
|
||||
|
||||
if [ "${#mime_types[@]}" -eq 0 ]; then
|
||||
echo " No regular files detected."
|
||||
else
|
||||
printf '%s\n' "${mime_types[@]}" \
|
||||
| sort \
|
||||
| uniq -c \
|
||||
| awk '{ printf " %-5s %s\n", $1, $2 }'
|
||||
echo
|
||||
printf " Total files: %d\n" "${#mime_types[@]}"
|
||||
fi
|
||||
|
||||
echo
|
||||
## 2) SUBDIRECTORY SIZES
|
||||
echo ">> Subdirectory inventory with sizes"
|
||||
# Identify each directory (excluding the current “.”) at depth=1
|
||||
mapfile -t subdirs < <(find . -maxdepth 1 -mindepth 1 -type d | sort)
|
||||
|
||||
if [ "${#subdirs[@]}" -eq 0 ]; then
|
||||
echo " No subdirectories present."
|
||||
else
|
||||
# Compute human-readable size for each
|
||||
for dir in "${subdirs[@]}"; do
|
||||
# du -sh prints: “<size> <path>”
|
||||
size=$(du -sh -- "${dir}" 2>/dev/null | awk '{print $1}')
|
||||
name="${dir#./}"
|
||||
printf " %-10s %s\n" "${size}" "${name}"
|
||||
done
|
||||
echo
|
||||
printf " Total subdirectories: %d\n" "${#subdirs[@]}"
|
||||
fi
|
||||
|
||||
echo "=== End of report ==="
|
||||
Loading…
Add table
Reference in a new issue