Skip to content

Instantly share code, notes, and snippets.

@tzi
Created September 24, 2012 21:52
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tzi/3778671 to your computer and use it in GitHub Desktop.
Save tzi/3778671 to your computer and use it in GitHub Desktop.
Pidoa - Rename TV shows files automatically

Pidoa

This script allow you to rename TV shows easily

Usage:    php ./pidoa.php <folder_path>  <pattern>
Example:  php ./pidoa.php ./             "Babylon 5 S%Sx%E %V"

Options: 
  %s : Season
  %S : Season on two digits
  %e : Episode
  %E : Episode on two digits
  %V : Version

You can set pidoa as a bash alias in your ~/.bashrc file

alias pidoa="php /my/path/to/the/script/pidoa.php"

You can launch it recursirvely, if the folder name is the name of the TV show

for i in *; do pidoa "\"$(pwd)/${i}\"" "${i}x%E %V"; done
<?php
function usage( $argv ) {
echo PHP_EOL .
'Pidoa' . PHP_EOL .
'------------' . PHP_EOL .
'This script allow you to rename tv shows easily' . PHP_EOL .
PHP_EOL .
'Usage: php ' . $argv[ 0 ] . ' <folder_path> <pattern>' . PHP_EOL .
'Example: php ' . $argv[ 0 ] . ' ./ "Babylon 5 S%Sx%E %V"' . PHP_EOL .
PHP_EOL .
'Options: ' . PHP_EOL .
' %s : Season' . PHP_EOL .
' %S : Season on two digits' . PHP_EOL .
' %e : Episode' . PHP_EOL .
' %E : Episode on two digits' . PHP_EOL .
' %V : VO' . PHP_EOL .
PHP_EOL;
}
function list_files( $path ) {
if ( $files = glob( $path ) ) {
return $files;
}
ob_start();
system( 'for i in ' . $path . '; do echo $i; done' );
$out = ob_get_contents();
ob_end_clean();
$files = explode( PHP_EOL, $out );
array_pop( $files );
return $files;
}
function preg_matches( $preg, $subject ) {
$matches = array( );
if ( preg_match( '@' . $preg . '@i', $subject, $matches ) ) {
return $matches;
}
return FALSE;
}
# ARGUMENT CONTROL
if ( count( $argv ) != 3 ) {
usage( $argv );
exit;
}
# VARIABLES
define( 'FOLDER_PATH', $argv[ 1 ] );
define( 'FILE_NAME_FORMAT', $argv[ 2 ] );
$episodes = array( );
# CLASS
class Episode {
private $file;
private $season;
private $episode;
private $version;
const ONE_REG = '([0-9]?[0-9])[xeXE]?([0-9][0-9])';
const DOUBLE_REG = '([0-9]?[0-9])[xeXE]?([0-9][0-9])[xeXE&-]([0-9]?[0-9])';
const MATCH_REG = '.*\.(avi|mpg|mpeg|mp4|mkv|srt)';
const V_REG = '([\. _-](VO|VOST|VF|VOSTFR)[\. _-])';
const VFR_REG = '([\. _-](fr|french)[\. _-])';
public function __construct( $file, $season, $episodes, $version ) {
$this->file = $file;
$this->season = $season;
if ( ! is_array( $episodes ) ) {
$episodes = array( $episodes );
}
$this->episodes = $episodes;
$this->version = $version;
}
public static function by_file( $file ) {
$matches = array( );
$filename = basename( $file );
// echo '-- ' . $filename . PHP_EOL;
if ( $matches = preg_matches( self::ONE_REG . self::MATCH_REG, $filename ) ) {
$season = intval( $matches[ 1 ] );
$episode = intval( $matches[ 2 ] );
$version = self::version_by_filename( $filename );
if ( $matches = preg_matches( self::DOUBLE_REG . self::MATCH_REG, $filename ) ) {
if ( $season === intval( $matches[ 1 ] ) && $episode === intval( $matches[ 2 ] ) ) {
$episode = array( intval( $matches[ 2 ] ), intval( $matches[ 3 ] ) );
}
}
return new self( $file, $season, $episode, $version );
}
return FALSE;
}
public static function version_by_filename( $filename ) {
$version = 'VO';
if ( $matches = preg_matches( self::V_REG, $filename ) ) {
$version = $matches[ 2 ];
} else if ( $matches = preg_matches( self::VFR_REG, $filename ) ) {
$version = 'VF';
}
return $version;
}
public function get_extension( ) {
return substr( $this->file, strrpos( $this->file, '.' ) + 1 );
}
public function get_filename( ) {
return basename( $this->file );
}
public function get_folder( ) {
return dirname( $this->file );
}
public function get_file_formated( $format ) {
return $this->get_folder( ) . '/' . $this->get_filename_formated( $format );
}
public function get_filename_formated( $format ) {
$pattern = array( '$s', '%S', '%e', '%E', '%v', '%V' );
$replace = array(
$this->season,
str_pad( $this->season, 2, '0', STR_PAD_LEFT ),
$this->episodes( ),
$this->episodes_pad( ),
$this->version,
$this->version
);
return str_replace( $pattern, $replace, $format ) . '.' . $this->get_extension( );
}
public function episodes( ) {
return implode( '-', $this->episodes );
}
public function episodes_pad( ) {
$pad = array( );
foreach ( $this->episodes as $episode ) {
$pad[ ] = str_pad( $episode, 2, '0', STR_PAD_LEFT );
}
return implode( '-', $pad );
}
public function rename_formated( $format ) {
rename( $this->file, $this->get_file_formated( $format ) );
}
}
# CODE !
$to_rename = FALSE;
$files = list_files( FOLDER_PATH . '/*' );
foreach ( $files as $file ) {
if ( $episode = Episode::by_file( $file ) ) {
$filename = $episode->get_filename( );
$new_filename = $episode->get_filename_formated( FILE_NAME_FORMAT );
echo $new_filename;
if ( $new_filename != $filename ) {
echo ' <- ' . $filename;
$to_rename = TRUE;
}
echo PHP_EOL;
$episodes[ ] = $episode;
}
}
if ( count( $episodes ) > 0 ) {
echo count( $episodes ) . ' episodes found' . PHP_EOL;
if ( $to_rename ) {
echo "Rename it (Y-n)? ";
$lets = substr( fgets( STDIN ), 0, -1 );
if ( $lets == 'Y' ) {
foreach ( $episodes as $episode ) {
$episode->rename_formated( FILE_NAME_FORMAT );
}
echo 'Renamed' . PHP_EOL;
} else {
echo 'Canceled' . PHP_EOL;
}
}
} else {
echo 'No episodes found' . PHP_EOL;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment