Skip to content

Instantly share code, notes, and snippets.

@pR0Ps
Created October 13, 2021 23:44
Show Gist options
  • Save pR0Ps/63d81dbb9b8862abe9a32f399dd3a91d to your computer and use it in GitHub Desktop.
Save pR0Ps/63d81dbb9b8862abe9a32f399dd3a91d to your computer and use it in GitHub Desktop.
Split large files into chunks that the Nintendo Switch OS + homebrew can read
#!/bin/bash
# Splits a file into pieces so it can be written to a FAT32 filesystem and read
# by the Nintendo Switch (after setting the archive bit on the folder).
# The original file is not preserved (although it can be easily recovered by
# catting the split files together).
# Will split file like so: file.ext --> file.ext/00, file.ext/01, etc
set -e
MAX_SIZE=4294901760 # 0xFFFF0000
if [ $# -ne 1 ]; then
echo "ERROR: provide a single file to split"
exit 1
elif ! [ -f "$1" ]; then
echo "ERROR: '$1' is not a file"
exit 1
fi
size=$(stat -c "%s" "$1")
blocks=$(( (size + (MAX_SIZE-1))/MAX_SIZE )) # divide, rounding up
if [ $blocks -lt 2 ]; then
echo "File is not large enough to require splitting"
exit 0
elif [ $blocks -gt 100 ]; then
echo "File is too large to split (max 100 pieces)"
exit 1
fi
echo "Will split '$1' into $blocks parts"
# Move file into directory of the same name as part 0
printf -v file "%s/%02d" "$1" 0
echo "Moving '$1' to '$file'"
tmp="$(mktemp --dry-run --tmpdir="$(dirname "$1")")"
mv "$1" "$tmp"
mkdir "$1"
mv "$tmp" "$file"
# Use tail and truncate to split data off the end of the file
for (( b=blocks-1; b > 0; b-- )); do
printf -v blockfile "%s/%02d" "$1" "$b"
offset=$((b * MAX_SIZE))
printf "Transferring bytes 0x%x-0x%x to '%s'\n" "$offset" "$size" "$blockfile"
blocksize=$((size-offset))
tail -c $blocksize "$file" > "$blockfile"
truncate -s $offset "$file"
size=$((size-blocksize))
done
echo "Done!"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment