Last active 1757270230

misyl's Avatar misyl revised this gist 1757270229. Go to revision

1 file changed, 147 insertions

relativize_symlinks.sh(file created)

@@ -0,0 +1,147 @@
1 + #!/bin/bash
2 +
3 + # Script to convert absolute symlinks to relative symlinks in a directory
4 + # Usage: ./relativize_symlinks.sh [directory]
5 +
6 + set -e
7 +
8 + # Function to calculate relative path from source to target
9 + calculate_relative_path() {
10 + local source="$1"
11 + local target="$2"
12 +
13 + # Convert to absolute paths to ensure consistency
14 + source=$(realpath -m "$source")
15 + target=$(realpath -m "$target")
16 +
17 + # Split paths into arrays
18 + IFS='/' read -ra source_parts <<< "${source#/}"
19 + IFS='/' read -ra target_parts <<< "${target#/}"
20 +
21 + # Find common prefix length
22 + local common_length=0
23 + local min_length=$((${#source_parts[@]} < ${#target_parts[@]} ? ${#source_parts[@]} : ${#target_parts[@]}))
24 +
25 + for ((i=0; i<min_length; i++)); do
26 + if [[ "${source_parts[i]}" == "${target_parts[i]}" ]]; then
27 + ((common_length++))
28 + else
29 + break
30 + fi
31 + done
32 +
33 + # Calculate number of directories to go up from source
34 + local up_dirs=$((${#source_parts[@]} - common_length - 1))
35 +
36 + # Build relative path
37 + local relative_path=""
38 +
39 + # Add ../ for each directory we need to go up
40 + for ((i=0; i<up_dirs; i++)); do
41 + if [[ -n "$relative_path" ]]; then
42 + relative_path="${relative_path}/.."
43 + else
44 + relative_path=".."
45 + fi
46 + done
47 +
48 + # Add the remaining target path components
49 + for ((i=common_length; i<${#target_parts[@]}; i++)); do
50 + if [[ -n "$relative_path" ]]; then
51 + relative_path="${relative_path}/${target_parts[i]}"
52 + else
53 + relative_path="${target_parts[i]}"
54 + fi
55 + done
56 +
57 + # Handle case where source and target are the same
58 + if [[ -z "$relative_path" ]]; then
59 + relative_path="."
60 + fi
61 +
62 + echo "$relative_path"
63 + }
64 +
65 + # Function to process symlinks in a directory
66 + process_directory() {
67 + local dir="$1"
68 + local base_dir="$2"
69 +
70 + echo "Processing directory: $dir"
71 +
72 + # Find all symbolic links in the directory
73 + while IFS= read -r -d '' symlink; do
74 + # Get the target of the symlink
75 + local target
76 + target=$(readlink "$symlink")
77 +
78 + # Check if it's an absolute path
79 + if [[ "$target" == /* ]]; then
80 + echo "Found absolute symlink: $symlink -> $target"
81 +
82 + # Calculate the directory containing the symlink
83 + local symlink_dir
84 + symlink_dir=$(dirname "$symlink")
85 +
86 + # Convert absolute target to be relative to base directory
87 + local adjusted_target="${base_dir}${target}"
88 +
89 + # Calculate relative path from symlink location to target
90 + local relative_target
91 + relative_target=$(calculate_relative_path "$symlink_dir/dummy" "$adjusted_target")
92 +
93 + echo " Converting to: $symlink -> $relative_target"
94 +
95 + # Remove the old symlink and create the new relative one
96 + rm "$symlink"
97 + ln -s "$relative_target" "$symlink"
98 +
99 + echo " ✓ Converted successfully"
100 + fi
101 + done < <(find "$dir" -type l -print0)
102 + }
103 +
104 + # Main script
105 + main() {
106 + local target_dir="${1:-.}"
107 +
108 + # Validate directory exists
109 + if [[ ! -d "$target_dir" ]]; then
110 + echo "Error: Directory '$target_dir' does not exist" >&2
111 + exit 1
112 + fi
113 +
114 + # Get absolute path of target directory to use as base
115 + local abs_target_dir
116 + abs_target_dir=$(realpath "$target_dir")
117 +
118 + echo "Relativizing symlinks in: $abs_target_dir"
119 + echo "Using current directory as filesystem root"
120 + echo
121 +
122 + # Process the directory
123 + process_directory "$target_dir" "$abs_target_dir"
124 +
125 + echo
126 + echo "Symlink relativization complete!"
127 + }
128 +
129 + # Show usage if --help is passed
130 + if [[ "$1" == "--help" || "$1" == "-h" ]]; then
131 + echo "Usage: $0 [directory]"
132 + echo
133 + echo "Convert absolute symlinks to relative symlinks in the specified directory."
134 + echo "If no directory is specified, the current directory is used."
135 + echo
136 + echo "Example:"
137 + echo " $0 ./extracted_filesystem"
138 + echo
139 + echo "This will convert symlinks like:"
140 + echo " usr/lib/libz.so -> /lib/libz.so.1.2.11"
141 + echo "To:"
142 + echo " usr/lib/libz.so -> ../../lib/libz.so.1.2.11"
143 + exit 0
144 + fi
145 +
146 + # Run main function
147 + main "$@"
Newer Older