diff --git a/MANIFEST b/MANIFEST index 3cfa97c..19c8e05 100644 --- a/MANIFEST +++ b/MANIFEST @@ -38,3 +38,5 @@ share/icons/user.png t/00-load.t t/kwalitee.t t/pod.t +utils/auto_perltidy.sh +utils/bak_cleaner.sh diff --git a/bin/gtk-pipe-viewer b/bin/gtk-pipe-viewer index 0f318e6..b77ea03 100755 --- a/bin/gtk-pipe-viewer +++ b/bin/gtk-pipe-viewer @@ -182,9 +182,9 @@ my %CONFIG = ( hpaned_position => 420, # Pipe options - dash_support => 1, - dash_mp4_audio => 1, - dash_segmented => 1, # may load slow + split_videos => 1, + m4a_audio => 1, + dash => 1, # may load slow prefer_mp4 => 0, prefer_av1 => 0, ignore_av1 => 0, @@ -854,7 +854,7 @@ sub apply_configuration { $audio_only_checkbutton->set_active($CONFIG{audio_only}); # DASH mode - $dash_checkbutton->set_active($CONFIG{dash_segmented}); + $dash_checkbutton->set_active($CONFIG{dash}); $clear_list_checkbutton->set_active($CONFIG{clear_search_list}); $panel_account_type_combobox->set_active($CONFIG{active_panel_account_combobox}); @@ -1742,7 +1742,7 @@ sub toggled_audio_only { # DASH mode sub toggled_dash_support { - $CONFIG{dash_segmented} = $dash_checkbutton->get_active() || 0; + $CONFIG{dash} = $dash_checkbutton->get_active() || 0; } # Check buttons toggles @@ -2978,9 +2978,9 @@ sub get_streaming_url { hfr => $CONFIG{hfr}, ignore_av1 => $CONFIG{ignore_av1}, - dash => $CONFIG{dash_support}, - dash_mp4_audio => $CONFIG{dash_mp4_audio}, - dash_segmented => $CONFIG{dash_segmented}, + split => $CONFIG{split_videos}, + m4a_audio => $CONFIG{m4a_audio}, + dash => $CONFIG{dash}, ); return { @@ -3141,13 +3141,12 @@ sub run_cli_pipe_viewer { sub get_options_as_arguments { my @args; my %options = ( - 'no-interactive' => q{}, - 'resolution' => $CONFIG{resolution}, - 'download-dir' => quotemeta(rel2abs($CONFIG{downloads_dir})), - 'fullscreen' => $CONFIG{fullscreen} ? q{} : undef, - 'no-dash' => $CONFIG{dash_support} ? undef : q{}, - 'no-dash-segmented' => $CONFIG{dash_segmented} ? undef : q{}, - 'no-video' => $CONFIG{audio_only} ? q{} : undef, + 'no-interactive' => q{}, + 'resolution' => $CONFIG{resolution}, + 'download-dir' => quotemeta(rel2abs($CONFIG{downloads_dir})), + 'fullscreen' => $CONFIG{fullscreen} ? q{} : undef, + 'no-dash' => $CONFIG{dash} ? undef : q{}, + 'no-video' => $CONFIG{audio_only} ? q{} : undef, ); while (my ($argv, $value) = each %options) { diff --git a/bin/pipe-viewer b/bin/pipe-viewer index 36ae20e..65ed5c0 100755 --- a/bin/pipe-viewer +++ b/bin/pipe-viewer @@ -163,10 +163,11 @@ my %CONFIG = ( : undef # auto-defined ), + split_videos => 1, + m4a_audio => 1, + # YouTube options - dash_support => 1, - dash_mp4_audio => 1, - dash_segmented => 1, # may load slow + dash => 1, # may load slow maxResults => 20, hfr => 1, # true to prefer high frame rate (HFR) videos resolution => 'best', @@ -604,21 +605,21 @@ if ($opt{history}) { } my $yv_obj = WWW::PipeViewer->new( - escape_utf8 => 1, - config_dir => $config_dir, - ytdl => $opt{ytdl}, - ytdl_cmd => $opt{ytdl_cmd}, - cache_dir => $opt{cache_dir}, - env_proxy => $opt{env_proxy}, - cookie_file => $opt{cookie_file}, - http_proxy => $opt{http_proxy}, - user_agent => $opt{user_agent}, - timeout => $opt{timeout}, - ); + escape_utf8 => 1, + config_dir => $config_dir, + ytdl => $opt{ytdl}, + ytdl_cmd => $opt{ytdl_cmd}, + cache_dir => $opt{cache_dir}, + env_proxy => $opt{env_proxy}, + cookie_file => $opt{cookie_file}, + http_proxy => $opt{http_proxy}, + user_agent => $opt{user_agent}, + timeout => $opt{timeout}, + ); require WWW::PipeViewer::Utils; my $yv_utils = WWW::PipeViewer::Utils->new(youtube_url_format => $opt{youtube_video_url}, - thousand_separator => $opt{thousand_separator},); + thousand_separator => $opt{thousand_separator},); { # Apply the configuration file my %temp = %CONFIG; @@ -806,9 +807,9 @@ usage: $execname [options] ([url] | [keywords]) --proxy=s : set HTTP(S)/SOCKS proxy: 'proto://domain.tld:port/' If authentication is required, use 'proto://user:pass\@domain.tld:port/' - --dash! : include or exclude the DASH itags - --dash-mp4a! : include or exclude the itags for MP4 audio streams - --dash-segmented! : include or exclude segmented DASH streams + --split-videos! : include or exclude the itags for split videos + --m4a-audio! : include or exclude the itags for M4A audio streams + --dash! : include or exclude segmented DASH streams --ytdl! : use youtube-dl for videos with encrypted signatures `--no-ytdl` will use invidious instances --ytdl-cmd=s : youtube-dl command (default: youtube-dl) @@ -1537,7 +1538,7 @@ sub parse_arguments { 'fixed-width|W|fw!' => \$opt{results_fixed_width}, 'captions!' => \$opt{videoCaption}, 'fullscreen|fs|f!' => \$opt{fullscreen}, - 'dash!' => \$opt{dash_support}, + 'split-videos!' => \$opt{split_videos}, 'confirm!' => \$opt{confirm}, 'prefer-mp4!' => \$opt{prefer_mp4}, @@ -1552,23 +1553,23 @@ sub parse_arguments { 'api-host|instance=s' => \$opt{api_host}, - 'convert-command|convert-cmd=s' => \$opt{convert_cmd}, - 'dash-m4a|dash-mp4-audio|dash-mp4a!' => \$opt{dash_mp4_audio}, - 'dash-segmented!' => \$opt{dash_segmented}, - 'wget-dl|wget-download!' => \$opt{download_with_wget}, - 'filename|filename-format=s' => \$opt{video_filename_format}, - 'rp|rem-played|remove-played-file!' => \$opt{remove_played_file}, - 'info|i|video-info=s' => \$opt{print_video_info}, - 'get-term-width!' => \$opt{get_term_width}, - 'page=i' => \$opt{page}, - 'novideo|no-video|n|audio!' => \$opt{novideo}, - 'highlight!' => \$opt{highlight_watched}, - 'skip-watched!' => \$opt{skip_watched}, - 'results=i' => \$opt{maxResults}, - 'shuffle|s!' => \$opt{shuffle}, - 'more|m!' => \$opt{more_results}, - 'pos|position=i' => \$opt{position}, - 'ps|playlist-save=s' => \$opt{playlist_save}, + 'convert-command|convert-cmd=s' => \$opt{convert_cmd}, + 'm4a-audio|mp4-audio!' => \$opt{m4a_audio}, + 'dash|dash-segmented!' => \$opt{dash}, + 'wget-dl|wget-download!' => \$opt{download_with_wget}, + 'filename|filename-format=s' => \$opt{video_filename_format}, + 'rp|rem-played|remove-played-file!' => \$opt{remove_played_file}, + 'info|i|video-info=s' => \$opt{print_video_info}, + 'get-term-width!' => \$opt{get_term_width}, + 'page=i' => \$opt{page}, + 'novideo|no-video|n|audio!' => \$opt{novideo}, + 'highlight!' => \$opt{highlight_watched}, + 'skip-watched!' => \$opt{skip_watched}, + 'results=i' => \$opt{maxResults}, + 'shuffle|s!' => \$opt{shuffle}, + 'more|m!' => \$opt{more_results}, + 'pos|position=i' => \$opt{position}, + 'ps|playlist-save=s' => \$opt{playlist_save}, 'ytdl!' => \$opt{ytdl}, 'ytdl-cmd=s' => \$opt{ytdl_cmd}, @@ -2965,27 +2966,27 @@ sub get_streaming_url { if (ref($captions) eq 'ARRAY' and @$captions and $opt{get_captions} and not $opt{novideo}) { require WWW::PipeViewer::GetCaption; my $yv_cap = WWW::PipeViewer::GetCaption->new( - auto_captions => $opt{auto_captions}, - captions_dir => $opt{cache_dir}, - captions => $captions, - languages => $CONFIG{srt_languages}, - yv_obj => $yv_obj, - ); + auto_captions => $opt{auto_captions}, + captions_dir => $opt{cache_dir}, + captions => $captions, + languages => $CONFIG{srt_languages}, + yv_obj => $yv_obj, + ); $srt_file = $yv_cap->save_caption($video_id); } require WWW::PipeViewer::Itags; state $yv_itags = WWW::PipeViewer::Itags->new(); - # Include DASH itags - my $dash = 1; + # Include split-videos + my $split_videos = 1; - # Exclude DASH itags in download-mode or when no video output is required - if ($opt{novideo} or not $opt{dash_support}) { - $dash = 0; + # Exclude split-videos in download-mode or when no video output is required + if ($opt{novideo} or not $opt{split_videos}) { + $split_videos = 0; } elsif ($opt{download_video}) { - $dash = $opt{merge_into_mkv} ? 1 : 0; + $split_videos = $opt{merge_into_mkv} ? 1 : 0; } my ($streaming, $resolution) = $yv_itags->find_streaming_url( @@ -2995,9 +2996,9 @@ sub get_streaming_url { hfr => $opt{hfr}, ignore_av1 => $opt{ignore_av1}, - dash => $dash, - dash_mp4_audio => ($opt{novideo} ? 1 : $opt{dash_mp4_audio}), - dash_segmented => ($opt{download_video} ? 0 : $opt{dash_segmented}), + split => $split_videos, + m4a_audio => ($opt{novideo} ? 1 : $opt{m4a_audio}), + dash => ($opt{download_video} ? 0 : $opt{dash}), ); return { @@ -4213,18 +4214,10 @@ The special tokens for C are listed in: pipe-viewer --tricks -=head2 dash_mp4_audio - -Include or exclude MP4/M4A (AAC) audio files. - -=head2 dash_segmented +=head2 dash Include or exclude streams in "Dynamic Adaptive Streaming over HTTP" (DASH) format. -=head2 dash_support - -Enable or disable support for split videos. - =head2 date Search for videos uploaded within a specific amount of time. @@ -4347,6 +4340,10 @@ Arguments for C how to merge the files. Include closed-captions inside the MKV container (if any). +=head2 m4a_audio + +When set to C<0>, MP4/M4A (AAC) audio files will be ignored. + =head2 order Search order for videos. @@ -4411,6 +4408,10 @@ When downloading, skip if the file already exists locally. Skip already watched/downloaded videos. +=head2 split_videos + +Enable or disable support for split-videos. "Split-videos" are videos that do not include audio and video in the same file. + =head2 srt_languages List of SRT languages in the order of preference. diff --git a/lib/WWW/PipeViewer.pm b/lib/WWW/PipeViewer.pm index ec63d73..c0350f9 100644 --- a/lib/WWW/PipeViewer.pm +++ b/lib/WWW/PipeViewer.pm @@ -989,11 +989,6 @@ sub _extract_streaming_urls { $self->_check_streaming_urls($videoID, \@results); - if (grep { $_->{url} =~ /\bsc=yes\b/ } @results) { - say STDERR ":: Contains SC = yes" if $self->get_debug; - ##return; - } - # Keep only streams with contentLength > 0. @results = grep { $_->{itag} == 22 or (exists($_->{contentLength}) and $_->{contentLength} > 0) } @results; diff --git a/lib/WWW/PipeViewer/Itags.pm b/lib/WWW/PipeViewer/Itags.pm index b5ff171..b5aee6d 100644 --- a/lib/WWW/PipeViewer/Itags.pm +++ b/lib/WWW/PipeViewer/Itags.pm @@ -41,90 +41,90 @@ Reference: http://en.wikipedia.org/wiki/YouTube#Quality_and_formats sub get_itags { scalar { - 'best' => [{value => 38, format => 'mp4'}, # mp4 (3072p) (v-a) - {value => 138, format => 'mp4', dash => 1}, # mp4 (2160p-4320p) (v) - {value => 266, format => 'mp4', dash => 1}, # mp4 (2160p-2304p) (v) + 'best' => [{value => 38, format => 'mp4'}, # mp4 (3072p) (v-a) + {value => 138, format => 'mp4', split => 1}, # mp4 (2160p-4320p) (v) + {value => 266, format => 'mp4', split => 1}, # mp4 (2160p-2304p) (v) ], - '2160' => [{value => 315, format => 'webm', dash => 1, hfr => 1}, # webm HFR (v) - {value => 272, format => 'webm', dash => 1}, # webm (v) - {value => 313, format => 'webm', dash => 1}, # webm (v) - {value => 401, format => 'av1', dash => 1}, # av1 (v) + '2160' => [{value => 315, format => 'webm', split => 1, hfr => 1}, # webm HFR (v) + {value => 272, format => 'webm', split => 1}, # webm (v) + {value => 313, format => 'webm', split => 1}, # webm (v) + {value => 401, format => 'av1', split => 1}, # av1 (v) ], - '1440' => [{value => 308, format => 'webm', dash => 1, hfr => 1}, # webm HFR (v) - {value => 271, format => 'webm', dash => 1}, # webm (v) - {value => 264, format => 'mp4', dash => 1}, # mp4 (v) - {value => 400, format => 'av1', dash => 1}, # av1 (v) + '1440' => [{value => 308, format => 'webm', split => 1, hfr => 1}, # webm HFR (v) + {value => 271, format => 'webm', split => 1}, # webm (v) + {value => 264, format => 'mp4', split => 1}, # mp4 (v) + {value => 400, format => 'av1', split => 1}, # av1 (v) ], - '1080' => [{value => 303, format => 'webm', dash => 1, hfr => 1}, # webm HFR (v) - {value => 299, format => 'mp4', dash => 1, hfr => 1}, # mp4 HFR (v) - {value => 248, format => 'webm', dash => 1}, # webm (v) - {value => 137, format => 'mp4', dash => 1}, # mp4 (v) - {value => 399, format => 'av1', dash => 1, hfr => 1}, # av1 (v) - {value => 46, format => 'webm'}, # webm (v-a) - {value => 37, format => 'mp4'}, # mp4 (v-a) - {value => 301, format => 'mp4', live => 1}, # mp4 (live) (v-a) - {value => 96, format => 'ts', live => 1}, # ts (live) (v-a) + '1080' => [{value => 303, format => 'webm', split => 1, hfr => 1}, # webm HFR (v) + {value => 299, format => 'mp4', split => 1, hfr => 1}, # mp4 HFR (v) + {value => 248, format => 'webm', split => 1}, # webm (v) + {value => 137, format => 'mp4', split => 1}, # mp4 (v) + {value => 399, format => 'av1', split => 1, hfr => 1}, # av1 (v) + {value => 46, format => 'webm'}, # webm (v-a) + {value => 37, format => 'mp4'}, # mp4 (v-a) + {value => 301, format => 'mp4', live => 1}, # mp4 (live) (v-a) + {value => 96, format => 'ts', live => 1}, # ts (live) (v-a) ], - '720' => [{value => 302, format => 'webm', dash => 1, hfr => 1}, # webm HFR (v) - {value => 298, format => 'mp4', dash => 1, hfr => 1}, # mp4 HFR (v) - {value => 247, format => 'webm', dash => 1}, # webm (v) - {value => 136, format => 'mp4', dash => 1}, # mp4 (v) - {value => 398, format => 'av1', dash => 1, hfr => 1}, # av1 (v) - {value => 45, format => 'webm'}, # webm (v-a) - {value => 22, format => 'mp4'}, # mp4 (v-a) - {value => 300, format => 'mp4', live => 1}, # mp4 (live) (v-a) - {value => 120, format => 'flv', live => 1}, # flv (live) (v-a) - {value => 95, format => 'ts', live => 1}, # ts (live) (v-a) + '720' => [{value => 302, format => 'webm', split => 1, hfr => 1}, # webm HFR (v) + {value => 298, format => 'mp4', split => 1, hfr => 1}, # mp4 HFR (v) + {value => 247, format => 'webm', split => 1}, # webm (v) + {value => 136, format => 'mp4', split => 1}, # mp4 (v) + {value => 398, format => 'av1', split => 1, hfr => 1}, # av1 (v) + {value => 45, format => 'webm'}, # webm (v-a) + {value => 22, format => 'mp4'}, # mp4 (v-a) + {value => 300, format => 'mp4', live => 1}, # mp4 (live) (v-a) + {value => 120, format => 'flv', live => 1}, # flv (live) (v-a) + {value => 95, format => 'ts', live => 1}, # ts (live) (v-a) ], - '480' => [{value => 244, format => 'webm', dash => 1}, # webm (v) - {value => 135, format => 'mp4', dash => 1}, # mp4 (v) - {value => 397, format => 'av1', dash => 1}, # av1 (v) - {value => 44, format => 'webm'}, # webm (v-a) - {value => 35, format => 'flv'}, # flv (v-a) - {value => 94, format => 'mp4', live => 1}, # mp4 (live) (v-a) + '480' => [{value => 244, format => 'webm', split => 1}, # webm (v) + {value => 135, format => 'mp4', split => 1}, # mp4 (v) + {value => 397, format => 'av1', split => 1}, # av1 (v) + {value => 44, format => 'webm'}, # webm (v-a) + {value => 35, format => 'flv'}, # flv (v-a) + {value => 94, format => 'mp4', live => 1}, # mp4 (live) (v-a) ], - '360' => [{value => 243, format => 'webm', dash => 1}, # webm (v) - {value => 134, format => 'mp4', dash => 1}, # mp4 (v) - {value => 396, format => 'av1', dash => 1}, # av1 (v) - {value => 43, format => 'webm'}, # webm (v-a) - {value => 34, format => 'flv'}, # flv (v-a) - {value => 93, format => 'mp4', live => 1}, # mp4 (live) (v-a) - {value => 18, format => 'mp4'}, # mp4 (v-a) + '360' => [{value => 243, format => 'webm', split => 1}, # webm (v) + {value => 134, format => 'mp4', split => 1}, # mp4 (v) + {value => 396, format => 'av1', split => 1}, # av1 (v) + {value => 43, format => 'webm'}, # webm (v-a) + {value => 34, format => 'flv'}, # flv (v-a) + {value => 93, format => 'mp4', live => 1}, # mp4 (live) (v-a) + {value => 18, format => 'mp4'}, # mp4 (v-a) ], - '240' => [{value => 242, format => 'webm', dash => 1}, # webm (v) - {value => 133, format => 'mp4', dash => 1}, # mp4 (v) - {value => 395, format => 'av1', dash => 1}, # av1 (v) - {value => 6, format => 'flv'}, # flv (270p) (v-a) - {value => 5, format => 'flv'}, # flv (v-a) - {value => 36, format => '3gp'}, # 3gp (v-a) - {value => 13, format => '3gp'}, # 3gp (v-a) - {value => 92, format => 'mp4', live => 1}, # mp4 (live) (v-a) - {value => 132, format => 'ts', live => 1}, # ts (live) (v-a) + '240' => [{value => 242, format => 'webm', split => 1}, # webm (v) + {value => 133, format => 'mp4', split => 1}, # mp4 (v) + {value => 395, format => 'av1', split => 1}, # av1 (v) + {value => 6, format => 'flv'}, # flv (270p) (v-a) + {value => 5, format => 'flv'}, # flv (v-a) + {value => 36, format => '3gp'}, # 3gp (v-a) + {value => 13, format => '3gp'}, # 3gp (v-a) + {value => 92, format => 'mp4', live => 1}, # mp4 (live) (v-a) + {value => 132, format => 'ts', live => 1}, # ts (live) (v-a) ], - '144' => [{value => 278, format => 'webm', dash => 1}, # webm (v) - {value => 160, format => 'mp4', dash => 1}, # mp4 (v) - {value => 394, format => 'av1', dash => 1}, # av1 (v) - {value => 17, format => '3gp'}, # 3gp (v-a) - {value => 91, format => 'mp4'}, # mp4 (live) (v-a) - {value => 151, format => 'ts'}, # ts (live) (v-a) + '144' => [{value => 278, format => 'webm', split => 1}, # webm (v) + {value => 160, format => 'mp4', split => 1}, # mp4 (v) + {value => 394, format => 'av1', split => 1}, # av1 (v) + {value => 17, format => '3gp'}, # 3gp (v-a) + {value => 91, format => 'mp4'}, # mp4 (live) (v-a) + {value => 151, format => 'ts'}, # ts (live) (v-a) ], - 'audio' => [{value => 172, format => 'webm', kbps => 192}, # webm (192 kbps) - {value => 251, format => 'opus', kbps => 160}, # webm opus (128-160 kbps) - {value => 171, format => 'webm', kbps => 128}, # webm vorbis (92-128 kbps) - {value => 140, format => 'm4a', kbps => 128}, # mp4a (128 kbps) - {value => 141, format => 'm4a', kbps => 256}, # mp4a (256 kbps) - {value => 250, format => 'opus', kbps => 64}, # webm opus (64 kbps) - {value => 249, format => 'opus', kbps => 48}, # webm opus (48 kbps) - {value => 139, format => 'm4a', kbps => 48}, # mp4a (48 kbps) + 'audio' => [{value => 172, format => 'webm', kbps => 192}, # webm (192 kbps) + {value => 251, format => 'opus', kbps => 160}, # webm opus (128-160 kbps) + {value => 171, format => 'webm', kbps => 128}, # webm vorbis (92-128 kbps) + {value => 140, format => 'm4a', kbps => 128}, # mp4a (128 kbps) + {value => 141, format => 'm4a', kbps => 256}, # mp4a (256 kbps) + {value => 250, format => 'opus', kbps => 64}, # webm opus (64 kbps) + {value => 249, format => 'opus', kbps => 48}, # webm opus (48 kbps) + {value => 139, format => 'm4a', kbps => 48}, # mp4a (48 kbps) ], }; } @@ -176,12 +176,12 @@ sub _find_streaming_url { $args{ignore_av1} && next; # ignore videos in AV1 format } - if ($itag->{dash}) { + if ($itag->{split}) { - $args{dash} || next; + $args{split} || next; my $video_info = $stream->{$itag->{value}}; - my $audio_info = $self->_find_streaming_url(%args, resolution => 'audio', dash => 0); + my $audio_info = $self->_find_streaming_url(%args, resolution => 'audio', split => 0); if (defined($audio_info)) { $video_info->{__AUDIO__} = $audio_info; @@ -191,14 +191,14 @@ sub _find_streaming_url { next; } - if ($resolution eq 'audio' and not $args{dash_mp4_audio}) { + if ($resolution eq 'audio' and not $args{m4a_audio}) { if ($itag->{format} eq 'm4a') { next; # skip m4a audio URLs } } # Ignore segmented DASH URLs (they load pretty slow in mpv) - if (not $args{dash_segmented}) { + if (not $args{dash}) { next if ($entry->{url} =~ m{/api/manifest/dash/}); } @@ -215,9 +215,12 @@ Return the streaming URL which corresponds with the specified resolution. ( urls => \@streaming_urls, resolution => 'resolution_name', # from $obj->get_resolutions(), - dash => 1/0, # include or exclude DASH itags - dash_mp4_audio => 1/0, # include or exclude DASH videos with MP4 audio - dash_segmented => 1/0, # include or exclude segmented DASH videos + + hfr => 1/0, # include or exclude High Frame Rate videos + ignore_av1 => 1/0, # true to ignore videos in AV1 format + split => 1/0, # include or exclude split videos + m4a_audio => 1/0, # incldue or exclude M4A audio files + dash => 1/0, # include or exclude streams in DASH format ) =cut diff --git a/utils/auto_perltidy.sh b/utils/auto_perltidy.sh new file mode 100755 index 0000000..866dcfa --- /dev/null +++ b/utils/auto_perltidy.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +alias perltidy='perltidy -utf8 -l=127 -f -kbl=1 -bbb -bbc -bbs -b -ple -bt=2 -pt=2 -sbt=2 -bvt=0 -sbvt=1 -cti=1 -bar -lp -anl'; +which perltidy; +cd ..; +for i in $(git status | grep '^[[:cntrl:]]*modified:' | egrep 'bin/|\.(pm|t)$' | perl -nE 'say +(split)[-1]'); do echo $i; perltidy -b $i; done diff --git a/utils/bak_cleaner.sh b/utils/bak_cleaner.sh new file mode 100755 index 0000000..cb8340e --- /dev/null +++ b/utils/bak_cleaner.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +for i in $(git status | grep \.bak$ | perl -nE 'say +(split)[-1]'); do echo $i; rm $i; done