Skip to content

Instantly share code, notes, and snippets.

@Eun
Last active June 5, 2025 08:13
Show Gist options
  • Save Eun/9a3c99873315c961ad3a8fd975071592 to your computer and use it in GitHub Desktop.
Save Eun/9a3c99873315c961ad3a8fd975071592 to your computer and use it in GitHub Desktop.
various m3u operations
#!/usr/bin/perl
use strict;
use warnings;
# Check if input file is provided
if (@ARGV != 2) {
die "Usage: $0 <input.m3u> <output.txt>\n";
}
my $input_file = $ARGV[0];
my $output_file = $ARGV[1];
open(my $in_fh, '<', $input_file) or die "Cannot open $input_file: $!";
open(my $out_fh, '>', $output_file) or die "Cannot open $output_file: $!";
my $count = 0;
while (my $line = <$in_fh>) {
chomp $line;
# Skip lines that don't start with http
next unless $line =~ m{^https?://};
# Remove default ports
$line =~ s{:80(/|$)}{$1};
$line =~ s{:443(/|$)}{$1};
print $out_fh "$line\n";
$count += 1;
}
close($in_fh);
close($out_fh);
print "Extracted $count urls and saved to $output_file\n";
#!/usr/bin/perl
use strict;
use warnings;
use File::Basename;
use File::Spec;
# Check command line arguments
if (@ARGV < 2 || @ARGV > 3) {
die "Usage: $0 <m3u_file> <directory> [attribute_name]\n" .
" Default attribute_name: tvg-name\n";
}
my ($m3u_file, $directory, $attribute_name) = @ARGV;
$attribute_name ||= 'tvg-name'; # Default to 'tvg-name' if not specified
# Check if the M3U file exists
unless (-e $m3u_file) {
die "Error: M3U file '$m3u_file' does not exist.\n";
}
# Check if the directory exists
unless (-d $directory) {
die "Error: Directory '$directory' does not exist.\n";
}
# Open the M3U file
open(my $fh, '<', $m3u_file) or die "Cannot open '$m3u_file': $!";
my %title_to_path;
my $current_title;
# Parse the M3U file
while (my $line = <$fh>) {
chomp $line;
# Skip empty lines and comments (except EXTINF)
next if $line =~ /^\s*$/;
next if $line =~ /^#EXTM3U/;
# Check for EXTINF line with specified attribute
if ($line =~ /^#EXTINF:.+?$attribute_name="(.+?)"/) {
$current_title = $1;
# Remove any characters that might be problematic in filenames
$current_title =~ s/[\/\\:*?"<>|]//g;
$current_title =~ s/^\s+|\s+$//g; # trim whitespace
}
# Process the file path line (following EXTINF)
elsif (defined $current_title) {
my $file_path = $line;
my $filename = fileparse($file_path);
# Store the mapping of original filename to new title (with original extension)
my ($name, $ext) = $filename =~ /(.+?)(\.[^.]*)?$/;
$title_to_path{$filename} = {
new_name => "$current_title$ext",
old_path => File::Spec->catfile($directory, $filename)
};
undef $current_title; # Reset for next entry
}
}
close($fh);
my $count = 0;
# Rename the files
foreach my $filename (keys %title_to_path) {
my $old_path = $title_to_path{$filename}{old_path};
my $new_name = $title_to_path{$filename}{new_name};
my $new_path = File::Spec->catfile($directory, $new_name);
if (-e $old_path) {
if (-e $new_path) {
warn "Warning: '$new_path' already exists. Skipping rename of '$old_path'.\n";
next;
}
if (rename($old_path, $new_path)) {
print "Renamed: '$filename' -> '$new_name'\n";
$count += 1;
} else {
warn "Error renaming '$old_path' to '$new_path': $!\n";
}
} else {
warn "Warning: File '$old_path' does not exist in directory.\n";
}
}
print "Renamed $count files\n";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment