Created
April 1, 2025 16:14
-
-
Save jbranchaud/53e0ea2e31db5ff97fa5ad72dad5ccc2 to your computer and use it in GitHub Desktop.
A script that you can run against any file/path to get a bunch of details about it
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# file_info.sh - A script to provide comprehensive information about a file | |
# Usage: ./file_info.sh <filename> | |
set -e | |
# Color definitions | |
RED='\033[0;31m' | |
GREEN='\033[0;32m' | |
YELLOW='\033[0;33m' | |
BLUE='\033[0;34m' | |
PURPLE='\033[0;35m' | |
CYAN='\033[0;36m' | |
NC='\033[0m' # No Color | |
print_header() { | |
echo -e "\n${BLUE}==== $1 ====${NC}\n" | |
} | |
print_section() { | |
echo -e "${CYAN}$1:${NC} $2" | |
} | |
print_error() { | |
echo -e "${RED}ERROR:${NC} $1" | |
} | |
print_warning() { | |
echo -e "${YELLOW}WARNING:${NC} $1" | |
} | |
print_success() { | |
echo -e "${GREEN}$1${NC}" | |
} | |
# Check if filename is provided | |
if [ $# -ne 1 ]; then | |
print_error "Usage: $0 <filename>" | |
exit 1 | |
fi | |
FILENAME="$1" | |
# Check if file exists | |
if [ ! -e "$FILENAME" ]; then | |
print_warning "File '$FILENAME' does not exist in the current directory." | |
# Check if file was in git history | |
if git rev-parse --is-inside-work-tree &>/dev/null; then | |
if git log --all -- "$FILENAME" &>/dev/null; then | |
print_header "GIT HISTORY FOR DELETED FILE" | |
# Last commit that involved the file | |
LAST_COMMIT=$(git log -n 1 --pretty=format:"%h - %an, %ar : %s" -- "$FILENAME") | |
print_section "Last commit" "$LAST_COMMIT" | |
# When the file was deleted | |
DELETION_COMMIT=$(git log -n 1 --diff-filter=D --pretty=format:"%h - %an, %ar : %s" -- "$FILENAME") | |
if [ -n "$DELETION_COMMIT" ]; then | |
print_section "Deleted in commit" "$DELETION_COMMIT" | |
fi | |
# When the file was added | |
CREATION_COMMIT=$(git log --diff-filter=A --pretty=format:"%h - %an, %ar : %s" -- "$FILENAME") | |
if [ -n "$CREATION_COMMIT" ]; then | |
print_section "Added in commit" "$CREATION_COMMIT" | |
fi | |
fi | |
fi | |
exit 1 | |
fi | |
print_header "BASIC FILE INFORMATION" | |
# Basic file information | |
print_section "File path" "$(realpath "$FILENAME")" | |
print_section "File size" "$(du -h "$FILENAME" | cut -f1)" | |
print_section "File type" "$(file -b "$FILENAME")" | |
if [ -f "$FILENAME" ]; then | |
print_section "Line count" "$(wc -l < "$FILENAME")" | |
FILEHASH=$(md5sum "$FILENAME" | cut -d ' ' -f 1) | |
print_section "MD5 hash" "$FILEHASH" | |
fi | |
# Owner and permissions | |
OWNER=$(stat -c '%U:%G' "$FILENAME") | |
PERMS=$(stat -c '%A' "$FILENAME") | |
print_section "Owner" "$OWNER" | |
print_section "Permissions" "$PERMS" | |
# Timestamps | |
print_section "Last modified" "$(stat -c '%y' "$FILENAME")" | |
print_section "Last accessed" "$(stat -c '%x' "$FILENAME")" | |
# Check if in git repository | |
if git rev-parse --is-inside-work-tree &>/dev/null; then | |
print_header "GIT INFORMATION" | |
# Get repo information | |
REPO_ROOT=$(git rev-parse --show-toplevel) | |
RELATIVE_PATH=$(realpath --relative-to="$REPO_ROOT" "$FILENAME") | |
print_section "Repository root" "$REPO_ROOT" | |
print_section "Path within repo" "$RELATIVE_PATH" | |
# Check if file is tracked by git | |
if git ls-files --error-unmatch "$FILENAME" &>/dev/null; then | |
print_success "File is under git version control" | |
# Check if file has modifications | |
if git diff --quiet -- "$FILENAME"; then | |
print_section "Status" "Clean (no modifications)" | |
else | |
print_section "Status" "Modified since last commit" | |
# Show a summary of changes | |
print_section "Changes summary" "$(git diff --stat "$FILENAME")" | |
fi | |
# Last few commits that modified the file | |
print_header "RECENT COMMIT HISTORY" | |
echo -e "$(git log -n 3 --pretty=format:"%h - %an, %ar : %s" -- "$FILENAME")" | |
# When the file was added to the repository | |
FIRST_COMMIT=$(git log --diff-filter=A --pretty=format:"%h - %an, %ar : %s" -- "$FILENAME") | |
print_header "ORIGIN INFORMATION" | |
if [ -n "$FIRST_COMMIT" ]; then | |
print_section "Added to repository in" "$FIRST_COMMIT" | |
else | |
print_warning "Could not determine when file was added to repository" | |
fi | |
else | |
print_warning "File is not under git version control" | |
# Check if file is ignored by git | |
if git check-ignore -q "$FILENAME"; then | |
print_section "Git status" "File is ignored by gitignore rules" | |
# Try to determine which rule ignores it | |
IGNORE_RULE=$(git check-ignore -v "$FILENAME" 2>/dev/null | awk '{print $2":"$3}') | |
if [ -n "$IGNORE_RULE" ]; then | |
print_section "Ignored by rule" "$IGNORE_RULE" | |
fi | |
else | |
print_section "Git status" "File is untracked but not ignored" | |
fi | |
fi | |
else | |
print_warning "Not inside a git repository" | |
fi | |
# Additional useful information based on file type | |
print_header "ADDITIONAL INFORMATION" | |
# For text files, provide some content insights | |
if file "$FILENAME" | grep -q text; then | |
if [ -f "$FILENAME" ]; then | |
print_section "Encoding" "$(file -b --mime-encoding "$FILENAME")" | |
# Check for shebang | |
SHEBANG=$(head -n 1 "$FILENAME" | grep -E "^#!" || echo "") | |
if [ -n "$SHEBANG" ]; then | |
print_section "Shebang" "$SHEBANG" | |
fi | |
# Check for potential secrets or sensitive info | |
if grep -q -E '(password|secret|token|key|credential)' "$FILENAME"; then | |
print_warning "File may contain sensitive information (passwords, keys, tokens, etc.)" | |
fi | |
# Check for TODO/FIXME comments | |
TODO_COUNT=$(grep -c -E 'TODO|FIXME' "$FILENAME" || echo "0") | |
if [ "$TODO_COUNT" -gt 0 ]; then | |
print_section "TODO/FIXME count" "$TODO_COUNT" | |
fi | |
fi | |
fi | |
# For executables, check execution bit | |
if [ -f "$FILENAME" ]; then | |
if [ -x "$FILENAME" ]; then | |
print_section "Executable" "Yes (execution bit is set)" | |
else | |
if file "$FILENAME" | grep -q -E 'executable|script'; then | |
print_warning "File appears to be executable but execution bit is not set" | |
fi | |
fi | |
fi | |
# For directories, show content summary | |
if [ -d "$FILENAME" ]; then | |
FILE_COUNT=$(find "$FILENAME" -type f | wc -l) | |
DIR_COUNT=$(find "$FILENAME" -type d | wc -l) | |
print_section "Contains" "$FILE_COUNT files in $DIR_COUNT directories" | |
print_section "Total size" "$(du -sh "$FILENAME" | cut -f1)" | |
fi | |
# For symlinks, show target | |
if [ -L "$FILENAME" ]; then | |
TARGET=$(readlink "$FILENAME") | |
print_section "Symlink target" "$TARGET" | |
if [ ! -e "$TARGET" ]; then | |
print_warning "Symlink target does not exist (broken link)" | |
fi | |
fi | |
exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment