Created
March 25, 2023 17:16
-
-
Save tdrnlds/c86710b607b3a26a685cd429f0ebb33b to your computer and use it in GitHub Desktop.
Move directories in which all the MKV and MP4 video files have only one hard link, designed for Unraid
This file contains hidden or 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
| #!/usr/bin/php | |
| <?php | |
| $source = '/mnt/cache/share'; | |
| $destination = '/mnt/disk1/share'; | |
| $threshold = 80; | |
| if( ! @file_exists( $source ) ) { | |
| echo "Bad source directory\n"; | |
| exit( 1 ); | |
| }; | |
| if( ! @file_exists( $destination ) ) { | |
| echo "Bad destination directory\n"; | |
| exit( 1 ); | |
| }; | |
| if( parse_ini_file( '/var/local/emhttp/var.ini' )[ 'mdResyncPos' ] ) { | |
| echo "Parity check or rebuild running. Exiting, for safety.\n"; | |
| exit( 2 ); | |
| }; | |
| function getFolderTree( $root, $dir = '' ) { | |
| $tree = []; | |
| foreach( array_diff( scandir( "$root$dir" ), [ '.', '..' ] ) as $name ) { | |
| if( is_dir( "$root$dir/$name" ) ) | |
| $tree = array_merge( $tree, getFolderTree( $root, "$dir/$name" ) ); | |
| elseif( is_file( "$root$dir/$name" ) ) | |
| $tree[] = "$dir/$name"; | |
| else { | |
| echo "This is neither a file, nor a directory: $root$dir/$name\n"; | |
| exit( 1 ); | |
| }; | |
| }; | |
| return $tree; | |
| }; | |
| function getSourceTree( $root, $dir = '' ) { | |
| return array_map( function( $file ) use ( $root ) { | |
| $stat = stat( "$root/$file" ); | |
| return [ 'node' => explode( '/', $file )[ 1 ], 'nlink' => $stat[ 'nlink' ], 'mtime' => $stat[ 'mtime' ] ]; | |
| }, array_filter( getFolderTree( $root ), function( $file ) { | |
| return substr( $file, -4 ) === '.mkv' || substr( $file, -4 ) === '.mp4'; | |
| } ) ); | |
| }; | |
| function sortSourceTree( $tree ) { | |
| usort( $tree, function( $a, $b ) { | |
| if( $a[ 'nlink' ] > $b[ 'nlink' ] ) | |
| return -1; | |
| if( $a[ 'nlink' ] < $b[ 'nlink' ] ) | |
| return 1; | |
| if( $a[ 'mtime' ] > $b[ 'mtime' ] ) | |
| return 1; | |
| if( $a[ 'mtime' ] < $b[ 'mtime' ] ) | |
| return -1; | |
| return 0; | |
| } ); | |
| return $tree; | |
| }; | |
| function filterSourceTree( $tree ) { | |
| for( $i = count( $tree ) - 1; $i >= 0; $i-- ) { | |
| for( $j = $i - 1; $j >= 0; $j-- ) { | |
| if( $tree[ $i ][ 'node' ] === $tree[ $j ][ 'node' ] ) { | |
| unset( $tree[ $i ] ); | |
| continue 2; | |
| }; | |
| }; | |
| if( $tree[ $i ][ 'nlink' ] > 1 ) { | |
| unset( $tree[ $i ] ); | |
| }; | |
| }; | |
| return $tree; | |
| }; | |
| function usage( $source ) { | |
| return ( disk_total_space( $source ) - disk_free_space( $source ) ) / disk_total_space( $source ) * 100; | |
| }; | |
| $tree = filterSourceTree( sortSourceTree( getSourceTree( $source ) ) ); | |
| while( ( $usage = usage( $source ) ) > $threshold && count( $tree ) > 0 ) { | |
| $next = array_shift( $tree ); | |
| echo "Copying: $source/{$next[ 'node' ]} -> $destination/{$next[ 'node' ]}\n"; | |
| exec( 'cp -a ' . escapeshellarg( "$source/{$next[ 'node' ]}" ) . ' ' . escapeshellarg( "$destination/{$next[ 'node' ]}" ), $out, $status ); | |
| if( $status === 0 ) { | |
| echo "Copy successful. Removing: $source/{$next[ 'node' ]}\n"; | |
| exec( 'rm -r ' . escapeshellarg( "$source/{$next[ 'node' ]}" ), $out, $status ); | |
| if( $status === 0 ) { | |
| echo "Remove successful. Moving on.\n"; | |
| } | |
| else { | |
| echo "Remove failed! Files exist in two places now. Oops. Moving on.\n"; | |
| }; | |
| } | |
| else { | |
| echo "Copying failed! Skipping remove, and moving on.\n"; | |
| }; | |
| }; | |
| if( $usage > $threshold ) { | |
| echo "Your disk is ", ceil( $usage ), "% full, but there is nothing left to move.\n"; | |
| exit( 2 ); | |
| }; | |
| echo "Your disk is down to ", ceil( $usage ), "% full.\n"; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment