1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853
|
#!@@perl@@
use warnings;
use strict;
# Open all other files as UTF-8.
use open qw{ :encoding(utf8) };
# Setup stdin, stdout and stderr according to locale.
use open qw{ :std :locale };
use ARename;
# documentation
=pod
=head1 NAME
arename - automatically rename audio files by tagging information
=head1 SYNOPSIS
arename [OPTION(s)] FILE(s)...
=head1 OPTIONS AND ARGUMENTS
=over 8
=item B<--ambiguous-use-first>
Sets the I<ambiguoususefirst> option. See below for details.
=item B<--compare-versions>
Prints the version of the arename script and the version of the Perl module,
that contains most of the code. These versions should be the same. If not,
that would indicate a possibly broken installation.
=item B<--copy> (short option: B<-c>)
Copy files instead of renaming (moving). This can be useful to copy tracks
from your audio archive to a portable device for example.
=item B<--debug>
Enable debugging output. This actually sets `I<verbosity>' to 10000. This output
option will cause very noisy output. You probably want something less verbose,
like `I<--verbosity 20>'.
=item B<--disable-hooks> (short option: B<-H>)
Do not make use of hooks of any sort (neither global nor local ones).
=item B<--disable-profiles> (short option: B<-N>)
Do I<not> use L<configuration profiles|/Configuration profiles> (see below).
Overwrites the B<useprofiles> setting.
=item B<--dryrun> (short option: B<-d>)
Go into dryrun mode. This means, that no action will be taken. B<arename>
will print what it would do, if called without I<-d>.
=item B<--enable-hooks>
Explicitly enable hooks.
=item B<--force> (short option: B<-f>)
Overwrite files if needed.
=item B<--help> (short option: B<-h>)
Display a short help text.
=item B<--list-cfg> (short option: B<-L>)
List the current configuration in the actual configuration format.
=item B<--list-file-types>
Lists all file types currently supported by B<arename>, one type
per line.
=item B<--list-exts-for-type> E<lt>type[,type[,...]]E<gt>
Lists all extensions recognised file name extsionsion for type
B<E<lt>typeE<gt>>, one extension per line. If a list of types is given
as a comma-separated list, extensions for all listed types are listed.
=item B<--list-profiles> (short option: B<-S>)
Print a list of profile names defined in the active configuration.
(This is primarily used by the zsh completion for the I<--profile> option.)
=item B<--read-local> (short option: B<-l>)
Read a local config file (./.arename.local). Overwrites the B<uselocalrc>
configuration setting.
=item B<--stdin> (short option: B<-s>)
Read filenames from stdin after processing files given on the command line.
It reads one file name per line, which means that file names containing
newlines are not supported.
=item B<--version> (short option: B<-V>)
Display version information.
=item B<--verbosity> E<lt>integer-valueE<gt>
Sets the `I<verbosity>' setting to `I<integer-value>'.
=item B<--suppress-skips> (short option: B<-Q>)
When a file is skipped, because its name would not change, this option will
cause B<arename> to suppress any output. This sets the `suppress_skips' option.
Note that if the `I<verbosity>' setting is at a high enough level, you may
still get messages about the file being processed in the first place.
=item B<--rc> E<lt>fileE<gt>
Read I<file> instead of ~/.arenamerc.
=item B<--post-rc> E<lt>fileE<gt>
Read I<file> B<after> ~/.arenamerc and B<before> ./.arename.local.
=item B<--prefix> E<lt>prefixE<gt> (short option: B<-p>)
Define a prefix for destination files.
=item B<--profile> E<lt>profile(s),...E<gt> (short option: B<-P>)
Define a list of one or more profiles to use forcibly, no matter if they
would be activated normally or not.
=item B<--compilation-template> E<lt>templateE<gt> (short option: B<-T>)
Define a template, that will be used for files that contain a compilation
tag.
=item B<--template> E<lt>templateE<gt> (short option: B<-t>)
Define a generic template (for all files that do I<not> contain a
compilation tag).
=item B<--userset> E<lt>I<variable>=I<value>E<gt> (short option: B<-u>)
Set a user defined variable to a given value (see
L</"User defined variables"> below).
=item I<FILE(s)...>
Input files, that are subject for renaming.
=back
A word about option name stability: With I<arename version 3.0> we are now
using Getopt::Long for parsing command lines options. That change was made,
because the meaningful single letter options where used up. Every option is
available via a I<--long-option>. B<That interface will remain stable>. If
changes to the I<--long-option> interface are done, that will happen with an
appropriate deprecation phase, so users can adjust. So, if you want to use
B<arename> in scripts, those are the options you should use. There are
currently no plans of removing or changing any further short options, but there
are no guarantees. If it is indeed better to change a short option, we will do
so.
A list of options that changed from B<arename> I<3.x> to I<4.0> can be found in
the project's CHANGES file and general advice about incompatible changes from
major version to major version are documented in the UPGRADING file.
=head2 Deprecated Command Line Options
The following options are deprecated and will be removed in a later version of
B<arename>.
=over 4
=item B<--quiet>
This option is a short hand for "--verbosity 10".
=item B<--uber-quiet>
This option is a short hand for "--verbosity 5".
=item B<--verbose>
This is a short hand for "--verbosity 20".
=back
=head1 DESCRIPTION
B<arename> is a tool that is able to rename audio files by looking at
a file's tagging information. It uses this information to assemble a
consistent destination file name. The user can define the format of the
destination filename by the use of template strings.
Templates can be defined in the L</Configuration files>, by the
I<template> and I<comp_template> settings (See L</SETTINGS> below).
By default, B<arename> will refuse to overwrite destination files,
if the file in question already exists. You can force overwriting by
supplying the B<--force> option.
In order to see what would happen instead of actually modifying files, you
can use the B<--dryrun> option. This way you can avoid problems, that would
occur if the situation (e.g. the information in the files or your
configuration) is not exactly as you expected it.
=head2 Supported file formats
Since version 4.0, B<arename> supports a lot more file formats than it
used to (version 3.0 only supported I<.mp3>, I<.ogg> and I<.flac>
files). Thanks to Audio::Scan, we now support a much wider range of
file types, of which most may exist using different file name
extensions (e.g. I<*.ogg> and I<*.oga> are both of the type I<ogg>).
You may use the `I<--list-file-types>' and `I<--list-ext-for-type>'
options to find out which file type is mapped to which file name
extensions.
If you would like support for another file type in B<arename>, you
will have to persuade the Audio::Scan developers to extend their
module with said feature. Adding support for it in B<arename> after
that should be trivial.
To give you an idea, arename (in connection with Audio::Scan B<0.85>)
lets you rename I<mp3>, I<mp4>, I<aac>, I<ogg>, I<flac>, I<asf>,
I<musepack>, I<monkey audio>, I<wav> (this type also supports I<aiff>)
and I<wavpack> files.
=head2 Inputting a *lot* of files
B<arename> can be used to keep the file names of whole audio archives in
sync. However, that means that you will have to tell the script the
location of many files, thousands maybe.
In order to do that you will face the problem, that on most UNIX-like
systems, the length of the argument list for external programs is limited
(recent Linux versions, as an exception, do not have that limitation
anymore).
So, even if your shell can do recursive globbing like ksh or zsh, this will
most likely get you into trouble (for more than just a few files):
% arename -d **/*.mp3
There are several ways to overcome that limitation, of course.
The first solution is to use B<find> in connection with B<arename>'s I<-s>
option:
% find . -name "*.mp3" -print | arename -d -s
This will break for file names that contain newlines, because I<--stdin> will
read one file name per line from the standard input stream.
Another way of using B<find> to deal with this problem is to use find's
I<-exec> option:
% find . -name "*.mp3" -exec arename -d '{}' '+'
This will work for every possible file name. No matter if it has spaces
or newlines in it. The I<+> at the end of the call causes find to call
the external program (B<arename> in this case) with as many arguments as
possible, without exceeding the limit. This requires a POSIXly correct
find. GNU find for instance, did not support the I<+> way for a long time.
If you are stuck with an old version, you can exchange the I<+> with a
I<;> (note, that a semicolon B<must> be quoted in any case), or use the
xargs tool instead.
A last solution for zsh users would be zargs (which requires
'autoload zargs' in your zsh configuration):
% zargs -- **/*.mp3 -- arename -d
=head1 GENERAL USAGE
When you are first confronted with B<arename> and you try to get started
with the documentation you might argue, that a 1000+ lines manual, that
is not filled with too many examples is hardly starter-friendly.
Therefore, this section was introduced to give you the bare minimum of
information in order to use the program without going through too much
fuzz.
If you are really afraid of documentation, you could of course just read
the output of the I<--help> option and see which options to provide in order
to get what you want. Then again, you will soon be pissed by the weird
default values B<arename> uses.
You will probably want other templates. After all, the ability to have
these expanded strings is one of the points to use B<arename> in the first
place. They are described in the TEMPLATE section; and reading that
section is the minimum effort you will want to go through.
After that, you can open the file I<~/.arenamerc> in your favourite
text editor and resemble the following text (and presumably change the
few values in there to your liking):
# now you certainly want your own templates, so define them here
# one for your normal files
template &artist - &album - &tracknumber. &tracktitle
# and another one for files that orignate from compilations
comp_template va - &album - &tracknumber. &artist - &tracktitle
If you want more automation or more customization, you will not get
around reading the manual below. If you need to solve special
problems, the L</HOOKS> part even further below is for you.
=head1 ENVIRONMENT VARIABLES
=over 8
=item B<ARENAME_LOAD_QUIET>
When set to I<1>, B<arename> will not output any startup messages; not
while reading the configuration or hook files, nor will B<arename> emit
messages about whether it is in copy mode or on a dry-run or similar.
However, if warnings or errors are encoutered while loading the
configuration, those messages are still emitted, of course.
Any other value but I<1> - and that includes ARENAME_LOAD_QUIET being
absent from the environment - will cause B<arename> to start up in
its normal manner.
=item B<ARENAME_SUPPRESS_COLOURS>
When set to I<1> (and only 1 - B<arename> will ignore any other setting),
arename will turn off its output colourations. As of version 4.0, B<arename>
uses Term::ANSIColor to produce output, that features terminal colours.
=back
=head1 FILES
B<arename>'s behaviour can be altered by a number of files it reads when
starting up.
Normal configuration tasks are done in (how convenient)
L</Configuration files>, described below.
If you need more control, or want to solve special problems you are having,
you can do so by supplying Perl code in L</Hook definition files>.
B<arename> can be configured to read configuration files as well as hook
definition files from the current working directory. This feature is
disabled by default, because they can be a security issue on multiuser
systems.
There are no such things as system wide configuration files in B<arename>.
For all setup files B<arename> tries to find (except for the local ones)
four different locations are tried. If the I<$XDG_CONFIG_HOME/arename>
directory exists, B<all> files are expected to be there. If that directory
does not exist, I<~/etc/arename/> and if that is not there I<~/.arename> are
are tried instead. If those directories could not be found either, B<arename>
will try to find the file it is looking for directly in the user's home
directory.
The default for I<$XDG_CONFIG_HOME> is I<~/.config>.
The first setup directory we find always wins. B<arename> does not consider
more than one setup directory.
If, for example, I<~/etc/arename/> exists and we are looking for the normal
L<configuration file|/Configuration files> (see below), but
I<~/etc/arename/rc> could not be found, we do B<not> try to find it in
I<~/.arename/> or the user's home directory.
=head2 Configuration files
B<arename> uses up to three configuration files. As for most programs,
the script will try to read a configuration file, that is located in the
user's I<home directory>. In addition to that, it will try to load I<local>
configuration files, if it finds appropriately named files in the
I<current directory> (and the I<uselocalrc> feature is enabled):
=over 8
=item B<$XDG_CONFIG_HOME/arename/rc>
=item B<~/etc/arename/rc>
=item B<~/.arename/rc>
=item B<~/.arenamerc>
per-user normal configuration file.
=item B<./.arename.local>
per-directory local configuration file (only read if I<uselocalrc> is set
or the I<--read-local> option is given on the command line).
=back
The per-user normal configuration file can be substituted by another file,
if specified via the I<--rc> option.
Last but not least, you can specify an intermediate configuration file,
that is read in between the normal and the per-directory file, via the
I<--post-rc> option.
=head3 File format
The format of the aforementioned files is pretty simple.
It is parsed line by line. Empty lines, lines only containing whitespace
and lines, whose first non whitespace character is a hash character (I<#>)
are ignored.
There are two different types of settings: boolean and scalar settings.
Booleans can be set like this:
<setting> [true|false]
If the value is omitted, I<true> is assumed. I<true> and I<false> are
recognized case insensitively, and a value of I<1> is synonymous to I<true>,
as is I<0> to I<false>.
Scalar settings are done in a very similar way:
<setting> <value>
If the value is omitted, string values will be set to an empty string and
numeric values will be set to zero.
In both cases, setting and value are separated by one or more whitespace
characters. The value will be the rest of the line (all of it, including
trailing whitespace).
If the value part starts with a backslash, that backslash is left out of the
value. That makes it possible to define templates with leading whitespace.
If a line contains only a string within square brackets, that string is the
start of a section. Section names are matches for starts of file names.
That means, the settings following such a section definition will only
applied for input file names that start with the same string as the section
name. Where file name means the string, handed over to B<arename>. The string
I<~/> at the beginning of a section name is expanded to the user's home
directory.
You may start as many sections as you would like.
A section named I</foo/bar/> supersedes a section named I</foo/> for a file
named I</foo/bar/baz.ogg>. So, the longest match wins.
Another possible configuration file entry is a user variable, which is
defined via the B<set> command. These settings are very different from the
normal settings. Therefore, they are defined in a different way. That way
is described in the L</User defined variables> subsection below.
Last but not least, you may define so called
L<profiles|/Configuration profiles>, see below.
=head3 Configuration profiles
Profiles are a very flexible and context sensitive way of using multiple
configuration files at once. With profiles, local configuration files (and
local hook definition files) can be substituted in a secure way; even on
multi-user systems.
Reading local files (configs and hook-files) is still supported for backwards
compatibility (see I<uselocalrc> and I<uselocalhooks> L<options|/SETTINGS>).
However, you are strongly encouraged to use profiles whenever you can.
As normal configuration files and global hook-files, profile-related files are
searched in one of the setup directories described above. They are using the
following naming conventions:
=over 8
=item B<$XDG_CONFIG_HOME/arename/profile.PROFILENAME>
=item B<~/etc/arename/profile.PROFILENAME>
=item B<~/.arename/profile.PROFILENAME>
=item B<~/.arename.PROFILENAME>
Profile related configuration files; read if I<PROFILENAME> is active.
They are read after a intermediate config file defined by I<--post-rc> and
a local config file (if enabled).
=item B<$XDG_CONFIG_HOME/arename/profile.PROFILENAME.hooks>
=item B<~/etc/arename/profile.PROFILENAME.hooks>
=item B<~/.arename/profile.PROFILENAME.hooks>
=item B<~/.arename.PROFILENAME.hooks>
Profile related L</Hook definition files> (see below for details); read if
I<PROFILENAME> is active.
These files are read, between global and local hook-definition files.
=back
In order to define profiles, you need to use the I<profile> keyword:
profile <name> <pattern>
Where I<name> is a string, that is used in the place of B<PROFILENAME>
in the file location lists above. This name may contain of the following
character range: B<a-zA-Z0-9_->
I<pattern> is part of a Perl regex pattern (see I<perlreref> and I<perlretut>
manpages). The pattern will be anchored at the beginning and is open at
the end, somewhat like this pseudocode:
if ($working_directory =~ m/^PATTERN/) { use_this_profile(); }
Example:
profile music /mnt/audio/music/
Will cause the profile I<music> to be active when the working directory is
I</mnt/audio/music/> or below. So, do not be afraid. You can use profiles
without understanding regular expressions.
Like many other values in B<arename>'s configuration, a leading backslash of
a pattern will be ignored to allow patterns, that start in white spaces.
Furthermore, if a pattern starts in I<~/>, that string is replaced by the
user's home directory.
You may add as many patterns to a profile name, as you want:
profile music /mnt/audio/music/
profile music /mnt/extern/audio/music/
The above activates the I<music> profile in I</mnt/audio/music/> and
I</mnt/extern/audio/music/>, for example.
More than one profile can be activated at the same time. If that is true,
the according configuration files are read in lexical order.
=head3 Sections versus Profiles
Since B<arename> provides two context sensitive configuration facilities,
you might ask yourself when to use which, when you are confronted with both
for the first time.
First of all, I<profiles> are more powerful. They may even introduce new
hooks for B<arename> to use. But that is not the conceptual difference
between the two.
I<sections> are sets of configuration settings, that are considered for
B<each and every> input file and they are B<only> enabled for input files,
whose name matches the section name.
I<profiles> on the other hand are sets of configuration and hook-definition
files, whose inclusion in the current B<arename> run is decided at the
B<beginning> of the program's execution (not for every input file) - namely,
if the name of the current working directory matches one of the profile's
patterns.
That means, that if you need to introduce slight configuration changes based
on an B<input file's name> you want to use a I<section>.
If you need to make broader configuration changes, considering the name of
the B<current working directory>, I<profiles> are the way to go.
Of course, profile configuration files may introduce new sections, too.
=head2 Configuration file example
# switch on verbosity
verbosity 20
# canonicalize file names before working with them
canonicalize
# the author is crazy! use a sane template by default. :-)
template &artist - &album (&year) - &tracknumber. &tracktitle
# activate the 'music' profile below /mnt/audio/music/.
profile music /mnt/audio/music/
# force files from /foo/bar/ to stay below that directory
[/foo/bar/]
prefix /foo/bar
=head2 Hook definition files
=over 4
=item B<$XDG_CONFIG_HOME/arename/hooks>
=item B<~/etc/arename/hooks>
=item B<~/.arename/hooks>
=item B<~/.arename.hooks>
Defines global hooks, that are in effect in every directory if the I<usehooks>
option is set to B<true>.
=item B<./.arename.hooks.local>
This allows you to define special hooks, that will only be applied for processes
that run in the directory the local file is found (and if the I<uselocalhooks>
option is set to B<true>).
=back
For details about hooks in B<arename>, see L</HOOKS> below.
=head1 SETTINGS
The following settings are supported in all configuration files.
Not all of them are usable in I<sections>. The ones you can use in
sections are: All I<default_*> options, I<force>, I<prefix>, I<sepreplace>,
I<tnpad>, I<comp_template> and I<template>.
=over 8
=item B<ambiguoususefirst>
Some tag types support setting the sametag multiple times. The
scanning backends before arename 4.0 did not support such tags. When
this option is set to I<false> (default), arename gives up when it
encounters such tags.
When set to I<true>, arename just uses the first value it encounters.
For maximum control over how tags with ambiguous values are handled,
you may use the `I<ambiguoustag>' hook. (default: I<false>)
=item B<canonicalize>
If set, a given file name will be transformed to its cleaned up absolute
path. You may want to set this, if you are using sections in the
configuration. If you do not use sections, all this will give you is a
performance penalty. (default value: I<false>)
=item B<checkprofilerc>
If set, B<arename> will check if there is a configuration file for a
profile as soon as it reads a profile definition in the setup and B<only>
consider the profile if it found the according config file. Profiles
without config file will cause a warning if this is set, which may cause the
I<dryrun> option to be set if the I<warningsautodryrun> option is set.
If unset, profiles without config file will not cause warnings. You will
see messages about missing configuration files, if a profile without config
file is active. (default: I<true>)
=item B<checktemplatesinitially>
If set, B<arename> will inspect all I<template> and I<comp_template>
settings for possible problems. Unsetting this option probably only
makes sense, if you are working with templates within hooks and know
what you are doing. Normal users will most likely want to stick with
the default. (default: I<on>)
=item B<comp_template>
Defines a template to use with files that provide a compilation tag
(for 'various artist' CDs, for example). This setting can still be
overwritten by the B<--compilation-template> command line option. (default
value: I<va/&album/&tracknumber - &artist - &tracktitle>)
=item B<default_*>
default_artist, default_album, default_compilation, default_genre,
default_tracknumber, default_tracktitle, default_year
Defines a default value, for the given tag in files, that lack this
information. (default value: I<undefined>)
=item B<hookerrfatal>
If this is set to false, arename will continue execution even if
reading, parsing or compiling a hooks file failed. (default value:
I<false>)
=item B<prefix>
Defines a prefix for destination files. Setting this to '/foo/bar' results
in destination files named '/foo/bar/Expanded Template.ogg'
This setting can still be overwritten by the B<--profile> command line option.
(default value: I<.>)
=item B<sepreplace>
Tagging information strings may contain slashes, which is a pretty bad
idea on most file systems. Therefore, you can define a string, that replaces
slashes with the value of this setting. (default value: I<_>)
=item B<suppress_skips>
Like the `I<--suppress-skips>' command line option, this disables messages for
files that B<arename> will skip because the file name would not change.
=item B<template>
Defines a template to use with files that do not provide a compilation tag
(or where the compilation tag and the artist tag are exactly the same).
This setting can be overwritten by the B<--compilation-template> command
line option. (default value:
I<&artist[1]/&artist/&album/&tracknumber - &tracktitle>)
=item B<template_aliases>
If this option is set, B<arename> allows the use of abbreviated taq
names in I<template> and I<comp_template>. See L</Available expression
identifiers> below for details. (default value: I<off>)
=item B<tnpad>
This defines the width, to which the track number field is padded with zeros
on the left. Setting this to zero disables padding. (default value: I<2>)
=item B<usehooks>
If set to true, use hooks defined in B<~/.arename.hooks>.
(default value: I<true>)
=item B<uselocalhooks>
If set to true, use hooks defined in B<./.arename.hooks.local>.
(default value: I<false>)
=item B<uselocalrc>
If set to true, read a local configuration file (B<./.arename.local>),
if it exists. (default value: I<false>)
=item B<useprofiles>
If set to true, configuration profiles will be used. If false, they are not.
(default value: I<true>)
=item B<usetypeasextension>
One file type may be used for different file name extensions. For
example, files matching I<*.ogg> and I<*.oga> will both be handled as
type I<ogg> in Audio::Scan (the information gathering backend,
B<arename> is using since version 4.0).
When this option is set to I<true>, a file matching I<*.oga> would be
renamed using I<.ogg> as the extension, since its type is
I<ogg>. Otherwise, the original extension is left untouched. (default:
I<true>)
=item B<verbosity>
Integer option, that sets the verbosity of I<arename>'s output. The default
value is `I<10>'. The `I<--verbosity>' option may be used to override this
setting.
=item B<warningsautodryrun>
Switches on the I<dryrun> option (if not enabled already), as soon as the
configuration file parser encounters non-fatal warnings. This option was
introduced to avoid destructive behaviour due to incorrect lines in any
of the configuration files. (default value: I<true>)
=back
=head2 Deprecated Settings
=over 4
=item B<verbose>
This setting has no effect and will be removed in a later version. Use an
appropriate `I<verbosity>' setting instead.
=item B<quiet>
This setting has no effect and will be removed in a later version. Use an
appropriate `I<verbosity>' setting instead.
=item B<quiet_skip>
This setting has no effect and will be removed in a later version. Use an
appropriate `I<verbosity>' setting instead.
=item B<debug>
This setting has no effect and will be removed in a later version. Use an
appropriate `I<verbosity>' setting instead.
=back
=head2 User defined variables
You can use the B<set> command in arenamerc files. This way the user can
define his own variables. The namespace is separate from B<arename>'s
normal settings. (That means, you cannot, for example, overwrite the
internal I<template> variable with this command.)
The sytnax is quite simple (and B<different> to normal settings on purpose!):
B<set> I<varname> = I<value>
There may be an arbitrary amount of whitespace around the equal sign
(including no whitespace at all). If you want to have a value that
starts in a whitespace character, you may start the value with a
backslash character (just like with the normal settings, a leading
backslash is always ignored).
You may also set user defined variables on the command line by using the
I<--userset> option:
% arename --userset variable0=value
% arename -u variable0=value
User defined variables are useful to make hooks configurable (see
L</HOOKS> below). Starting with version 4 of B<arename>, user defined
variables may also be defined within sections, which (just like normal
option) makes them applicable only if said section is used for a given
file.
=head1 TEMPLATE FORMAT
B<arename>'s templates are fairly easy to understand, but powerful.
At simplest, a template is just a fixed character string. However,
that would not be exactly useful, because then every file you would
ever want to rename would be getting the exact same name. That is why
B<arename> is able to expand certain expressions with information
gathered from the file's tagging information.
An expression basically looks like one of the following forms:
=over 8
=item B<&>I<identifier>
This is the `B<trivial>' expression. It will expand to the information
stored within the corresponding tag. If the tag in question is not
available, the expansion of the template string will fail.
=item B<&>I<identifier>B<[>I<length>B<]>
The `B<sized>' expression. The I<length> modifier in square brackets
defines the maximum length, to which the expression should be
expanded.
That means, if the artist of a file reveals to be 'I<Frank Zappa>',
then using 'B<&artist[1]>' will expand to 'I<F>'.
=item B<&{>I<identifier>B<:>I<default-template>B<}>
This is the first complex expression, called `B<complex-default>'. When
the tag, which corresponds to `I<identifier>' is available, this
expression will expand exactly like the trivial expression would.
If it is B<not> available though, the expansion doesn't fail, but
instead the `I<default-template>' string is expanded.
=item B<&{>I<identifier>B<?>I<set-template>B<!>I<unset-template>B<}>
This expansion is called `B<complex-set-unset>'. Again, what will be
used during template expansion depends on whether the tag which
corresponds to `I<identifier>' is set or not.
If it is B<set>, the string I<set-template> is expanded; if it is
B<unset>, the I<unset-template> string is used.
=back
Both simple expansions may be used with braces, like the complex
expansions are:
=over 8
=item B<&{>I<identifier>B<}>
This is equal to `B<&identifier>'.
=item B<&{>I<identifier[length]>B<}>
And this is equal to `B<&identifier[length]>'.
=back
Backslashes are special in template strings, because they are used to
quote characters that bear special meaning (for example, to get a
ampersand character, you need to use "B<\&>"). To get an actual
backslash in the resulting string, you need to use a backslash, quoted
by a backslash. A backslash on non-special characters is silently
dropped.
=head2 Nesting expressions
In complex expressions, the strings called `I<default-template>',
`I<set-template>' and `I<unset-template>' are subject to regular
template expansion. Hence, expressions like the following are
possible:
"&{album?&album/!}"
If `B<album>' were set, it would expand to its value followed by a
slash; otherwise it would expand to nothing. Using this, it is fairly
easy to deal with album-less tracks:
"&artist/&{album?&album/&tracknumber. !-no-album-/}&tracktitle"
That will effectively use the following template if `B<album>' is set:
"&artist/&album/&tracknumber. &tracktitle"
But if it is not set, it will instead use this:
"&artist/-no-album-/&tracktitle"
Caution has to be taken if certain characters are to be used within
conditional template expressions. For example, to use a closing curly
bracket in either of them, it needs to be quoted using a backslash
character.
Similarly, if an exclamation mark is to be used in a
`I<set-template>', it needs to be quoted by a backslash to avoid the
character being interpreted as the end of the `I<set-template>'
string.
=head2 Available expression identifiers
The data, that is expanded is derived from tagging information in the
audio files. There are two kinds of information available. One is the
purely informational tag (like a track's artist) and the other further
describes the format of the audio file (like the file's bitrate).
If you are defining a lot of templates on the command line, you may
find that these identifiers take quite a while to type. If the
I<template_aliases> option is set, you may use shorter alias names
instead of the the real identifier. Available aliases are listed with
their corresponding idetifier below.
This is a list of all informational identifiers available for
B<all> file-types:
=over 8
=item B<album>
The album the currently processed track is part of. (alias: I<al>)
=item B<artist>
The artist for the current track. (alias: I<ar>)
=item B<compilation>
Compilation tags are not very stable across different file
types. Usually, this is set to a string like "I<Various Artists>" for
tracks that are part of some sort of compilation album (like motion
picture sound-tracks). (alias: I<cmp>)
=item B<genre>
The genre or content type of the audio file. (alias: I<gn>)
=item B<tracknumber>
The number of the position of the track on the disc. Obviously. However, this
can be in the form of '12' or '12/23'. In the second form, only the part left
of the slash is used. The tracknumber is a little special, as you can define
to what width it should be padded with zeros on the left (see I<tnpad> setting
in L</SETTINGS>). (alias: I<tn>)
=item B<tracktitle>
The title of the currently processed track. (alias: I<tt>)
=item B<year>
Chronological information about the track (usually the year a song was
written or the year the album a track is part of was
released). (alias: I<yr>)
=back
Here is a list of file-format information tag available for B<all>
file-types:
=over 8
=item B<bitrate>
The bitrate the file was recorded/encoded with. (alias: I<br>)
=item B<channels>
The number of channels available in the file (for example, this is `2'
for stereo files). (alias: I<ch>)
=item B<length_ms>
The length of the track in milli-seconds. (alias: I<ln>)
=item B<samplerate>
The samplerate the file was recorded/encoded with. (alias: I<sr>)
=back
For B<all> file-types, the following tags are generated from the ones
listed above (for convenience):
=over 8
=item B<kbitrate>
Kilobits per second (bitrate / 1000). (alias: I<kbr>)
=item B<ksamplerate>
Kilosamples per second (samplerate / 1000). (alias: I<ksr>)
=item B<length_sec>
The length of the track in seconds. (alias: I<ls>)
=back
Some tags are only available for certain file-types. They are always
called `I<type_>B<*>'. File-type specific identifiers do not have
alias names. Here is a list of those tags:
=over 8
=item B<flac_wordsize>
The word-size used in a flac file. `24' if samples are 24 bits wide.
=item B<mp3_id3_version>
The version of the id3 tag used in mp3 files (e.g. "B<ID3v2.3.0>").
=item B<wav_id3_version>
The same as `I<mp3_id3_version>', but for wave files.
=back
=head1 EXIT STATUS
B<arename> returns zero if everything went fine; non-zero on fatal
problems. This may change in future versions.
=head1 HOOKS
Before we start, a word of warning: Hooks can solve a lot of problems.
That amount of flexibility comes at its price. All data passed to
hook functions are B<references> to the B<actual data> in the script
(except for the namespace argument, which is a copy). If you write
hooks carelessly, arename will get back at you! HOOKS ARE A BIG
HAMMER, THAT CAN CRUSH PROBLEMS AS WELL AS LIMBS!
I<You have been warned!>
=head2 Discussion
The reason for implementing hooks was to have a simple way of post
processing tags, filenames etc. without having to invent own magic in
the configuration files, when Perl has regular expressions on steriods
anyway. Hooks can do more then pure pre and post processing, because
they are called in numerous places and give broad access to the script's
data structures. Still, post processing is probably the most useful
feature they implement.
Hooks are just Perl subroutines, which are defined in one of two files
(see L</FILES>). They are run at certain events during the
execution of arename. The contents of the argument list for each hook
depends on what hook is called (see the L</List of hook events> below).
However, the first argument (argument zero aka. $_[0]) to all hooks is
the hook namespace, the subroutine is called in.
The global hooks file is read before the local one, which means, that
this local file may overwrite and extend the definitions from the global
file, as much as Perl permits. This also means, that hooks from the
local file are run I<after> the ones from the global file (unless you
are using your own method of registering hooks; but if you do so, you
know what you are doing anyway).
Subroutines must be registered to arename, to be known as hooks.
Once registered, a subroutine can be removed from the known hooks,
if requested (see L</Utility subroutines> below).
The keys in various data hashes passed to the hooks can be one of
the following: I<album>, I<artist>, I<compilation>, I<genre>,
I<tracknumber>, I<tracktitle>, I<year>.
=head2 Utility subroutines
=head3 Registration subroutines
There are two subroutines, that are used to tell arename about
subroutines, you defined that shall become hooks.
=over 4
=item B<register_hook>(I<event>, I<coderef>)
Registers a I<code reference> (read: your subroutine) for the given
I<event>. Example: register_hook('startup', \&custom_banner);
=item B<remove_hook>(I<event>, I<coderef>)
Removes B<all> entries of the I<code reference> for the given
I<event>. Example: remove_hook('startup', \&custom_banner);
If the coderef was added more than once, all entries are removed.
=back
=head3 File access and manipulation
The currently processed file name can be accessed via two subroutines:
=over 4
=item B<get_file>()
Returns the current file name as a string. This way, you can get the
name of the currently processed file in every hook.
=item B<set_file>(I<file name string>)
This gives you the opportunity of manipulating the current file name.
Be careful using this, because if you break the file name, B<arename>
cannot work properly.
=back
With these, you could even change the file name of the processed file,
while B<arename> works on it (which you really should only do, if you
know what you are doing).
=head3 User-defined-variable subroutines
Hooks can also use the data from user defined variables, via their Perl
interface:
=over 4
=item B<user_get>(I<setting>)
Returns the current value of I<setting>. This is always a scalar value.
=item B<user_set>(I<setting>, I<value>)
Change the value of I<setting> to I<value>.
=back
Here is an example for user defined settings:
# Assume, the user set the myvar-variable to "bar" in his
# configuration file
my $foo = user_get('myvar'); # $foo is now "bar"
user_set('foo', "bar, baz");
my $foo = user_get('myvar'); # $foo is now "bar, baz"
=head3 API for accessing to arename's internal configuration
You can also access the configuration data of B<arename> itself:
=over 4
=item B<get_opt>(I<setting>)
Returns the current value of I<setting>. This is always a scalar value.
=item B<set_opt>(I<setting>, I<value>)
Change the value of I<setting> to I<value>.
=back
A list of settings B<arename> will use: canonicalize, dryrun, force,
hookerrfatal, prefix, quiet, quiet_skip, readstdin, sepreplace, tnpad,
usehooks, uselocalhooks, uselocalrc, verbose, verbosity, comp_template and
template.
If you want to actually change these settings, you should have a profound
knowledge of B<arename>'s internals. Be careful.
=head3 API for default_* settings
If you need to access the current values of the I<default_*> settings:
=over 4
=item B<get_defaults>(I<tagname>)
Returns the value of default_I<tagname>.
=item B<get_default_keys>()
Returns a lexically sorted array of tag names of currently set I<default_*>
values.
=item B<set_default>(I<tagname>, I<value>)
Sets the value of default_I<tagname> to I<value>.
=back
=head3 Miscellaneous subroutines
And finally, a few miscellaneous functions ARename.pm provides, that
might be of interest.
=over 4
=item B<choose_template>(I<data hash reference>)
Return the appropriate template (I<normal> versus I<compiliation> template)
by the data in the referenced data hash.
=item B<expand_template>(I<template string>, I<data hash reference>)
Return the expanded version of I<template string>. The information, that
is used to do the expansion is taken from the referenced data hash.
Keep in mind that this function calls hooks itself. Avoid endless loops!
See L</Hooks when expanding the template> for details.
=item B<ensure_dir>(I<directory>)
Makes sure I<directory> exists. Think: mkdir -p I<directory>
=item B<file_eq>(I<file0>, I<file1>)
Checks if the name I<file0> and the name I<file1> point to the same file.
Returns I<0>, if one of the file names does not exist or if the files do
not point to the same file, I<1> otherwise.
Dies if it cannot stat one of the given files.
=item B<tag_supported>(I<tagname>)
Returns I<1> if the tag I<tagname> is supported by arename, I<0> otherwise.
=item B<template_deep_inspect>(I<template_string>)
This tokenises a template string and then looks at the whole token
tree, and tries to figure out any potential problems in it.
If tokenisation already failed, a negative value is returned. In case
of any warnings with the token tree, zero is returned. If nothing came
up, a positive value is returned.
This subroutine is called for the `I<template>' and `I<comp_template>'
strings in all sections when B<arename> starts. If the user chooses to
change a template string in a hook it is recommended to use this
function to avoid any errors due to broken templates.
=item B<xrename>(I<src>, I<dest>)
Renames I<src> to I<dest>. Works across file systems, too. Dies
if something fails.
=back
=head2 List of hook events
This is a complete list of hooks events with descriptions.
The first argument (argument number "zero") for every hook is the
name space they are called in. To find out the name of the currently
processed file, use the I<get_file>() subroutine described above.
=head3 Hooks in the main loop
These hooks are called at the highest level of the script.
=over 4
=item B<canonicalize>
This is called in the middle of the file name canonicalization process
(but B<only> if the I<canonicalize> setting is set).
You can get the current file name via I<get_file()>. The canonicalized
file name is handed to you via the hook's arguments. The value from
this argument will be assigned to the processed filename after the
execution of this hook.
I<Arguments>: B<1:> canonicalized file name
=item B<next_file_early>
Called at the start of the main loop I<before> any file checks and
canonicalizations (if enabled) are done.
I<Arguments>:
=item B<next_file_late>
Called in the main loop I<after> the file checks and canonicalizations
are done.
In this context, file checks means tests for read-access and for
whether the processed file is a symlink. B<arename> will refuse to
process symlinks and files it cannot read.
I<Arguments>:
=item B<file_done>
Called in the main loop I<after> the file has been processed (unless
B<filetype_unknown> was triggered, see below).
I<Arguments>:
=item B<filetype_unknown>
Called in the main loop I<after> the file was tried to be processed but
the file type (the extension, specifically) was unknown.
I<Arguments>:
=item B<filetype_known>
Called when it has been established, that the file in question should
theoretically be supported by arename.
I<Arguments>: B<1:> the current file name extension B<2:> the file
type that has been detected
=item B<pre_rename>
This is triggered directly before the actual file renaming process
starts. All information about the file has been gathered at this
point.
I<Arguments>: B<1:> the file type, B<2:> the extension that will be
used to assemble the target filename, B<3:> the data hash
=back
=head3 Hooks in the renaming procedure
When all data has been gathered, B<arename> will go on to actually
rename the files to their new destination name (which will be generated
in the process, see L</Hooks when expanding the template> below).
=over 4
=item B<pre_apply_defaults>
This is the first action to be taken in the renaming process. It is
called even before the default values are applied.
I<Arguments>: B<1:> data hash, B<2:> file extension
=item B<pre_template>
Called I<before> template expansions have been done.
I<Arguments>: B<1:> data hash, B<2:> file extension
=item B<post_template>
Called I<after> the template has been expanded and the new file name
has been completely generated (including the destination directory
prefix).
I<Arguments>: B<1:> data hash, B<2:> file extension
B<3:> the generated new filename (including directory prefix and file
extension)
=item B<post_ensure_dir>
The destnation directory for the new file name may contain sub directories,
which currently do not exist. This hook is called I<after> it is ensured,
every directory portion exists.
I<Arguments>: B<1:> data hash, B<2:> file extension
B<3:> the generated new filename (including directory prefix and file
extension)
=item B<post_rename>
This is the final hook in the actual renaming process. The file has been
renamed at this point.
I<Arguments>: B<1:> data hash, B<2:> file extension
B<3:> the generated new filename (including directory prefix and file
extension)
=back
=head3 Hooks when expanding the template
These hooks are called when the template string is filled with the data
from tags in the audio files. To do this, B<arename> first tokenises the
template string into a data structure, which is later used to assemble
the target file name.
=over 4
=item B<pre_expand_template>
Called before any expansions are done.
I<Arguments>: B<1:> the template string, B<2:> the data hash
=item B<post_expand_template>
Called after all expansions have been done, right before the the resulting
string is returned.
I<Arguments>: B<1:> the template string (fully expanded), B<2:> the data
hash
=item B<expand_template_pre_expand_tag>
Called each time the value of an existing tag is expanded. This may be
more than once, as tags may be used as often in a template as the user
requires. At each point, this hook will be called right before the
data was retrieved and post-processed (like zero-padding the
`tracknumber' tag).
I<Arguments>: B<1:> the tag's name, B<2:> the data hash
=item B<expand_template_unknown_tag>
This hook gets called whenever arename tries to expand a tag within a template,
for which it does not have any data available.
I<Arguments>: B<1:> the supposedly expanded string (`undef' upon hook-entry),
B<2:> the tag's name, B<2:> the data hash
=item B<expand_template_post_expand_tag>
Called each time the value of an existing tag is expanded. Like with
the `expand_template_pre_expand_tag' hook, this may be more than once.
At each point, this hook will be called right after the data was
retrieved and post-processed.
I<Arguments>: B<1:> the value, which will be used for expansion, B<2:>
the tag's name, B<2:> the data hash
=back
=head3 Hooks while gathering information
These hooks are triggered while the tag information is extracted from
the audio files B<arename> is processing. This is done in two
steps. First the Audio::Scan module is used to scan for the raw meta
data information from the current file. Then B<arename>'s data hash is
being filled with that data.
=over 4
=item B<pre_scan>
This hook is called right before any scanning has been done.
I<Arguments>: B<1:> the type of the file being processed (`ogg' for
ogg vorbis files)
=item B<post_scan>
This is triggered as soon as Audio::Scan is done processing the
current file, but before B<arename>'s data hash has been filled.
I<Arguments>: B<1:> the type of the file being processed (`ogg' for
ogg vorbis files), B<2:> the data structure returned by `Audio::Scan'
=item B<ambiguoustag>
When the data hash is being filled it is possible, that for one
B<arename> tag (like `artist') multiple values where returned by
Audio::Scan. This hook is triggered as soon as such a tag with
ambiguous values is processed.
The hook may be used for maximum control over how ambiguous values are
handled. To do this, the ambiguous value (passed as an array reference
in the second argument) should be turned into the desired scalar
value.
If the array reference is left as it is, the usual `ambiguoususefirst'
behaviour is followed. The the option's description for details.
I<Arguments>: B<1:> the name of the tag with the ambiguous value,
B<2:> its current (ambiguous) value, B<3:> the data hash in its
current form (obviously not all values will have been filled in at
this point), B<4:> the data structure returned by Audio::Scan (see its
documentation for details)
=item B<post_fill>
Finally, the `post_fill' hook is called after the data hash has been
filled. This is a good spot, if post-processing the values of
individual tag is desired.
I<Arguments>: B<1:> return code of the filling process (`0' in case of
an error, `1' otherwise), B<2:> the type of the file being processed
(`ogg' for ogg vorbis files), B<3:> the data structure returned by
`Audio::Scan', B<4:> the data hash.
=back
=head3 Miscellaneous hooks
=over 4
=item B<apply_defaults>
This is triggered before values from the default_* settings are applied
to missing values in the audio file. This hook is I<only> run if a
default value for a tag will be used!
I<Arguments>: B<1:> data hash, B<2:> current key
=item B<startup>
Called directly after all the module initialisation is done, at the very
start of the script. Configuration files will have been read, as well as
hook files (obviously) and command line options will have been handled at
this point already.
This hook may be useful for postprocessing the configuration as well as
for debugging.
I<Arguments>: B<1:> program name, B<2:> its version, B<3:>
configuration hash, B<4:> array of supported tags, B<5:> the program's
argument list
=item B<normal_quit>
Called at the end of the script. This is reached if nothing fatal happened.
I<Arguments>: B<1:> the program's argument list
=back
=head2 Example
First, to give you an idea about how argument passing works in B<arename>
hooks, take a look at these two `I<startup>' hooks:
sub print_banner0 {
# Yes, everything handed over to hooks (except for the namespace)
# are references. This gives us simple two way communication, but
# it's also a pretty big responsibility to handle. Think before
# screwing up. :)
my ($ns, $nameref, $verref, $confref, $suptagsref, $argvref) = @_;
print "BANNER! $$nameref $$verref " . $argvref->[0] . "\n";
# The following actually changes the $NAME variable, used
# in ARename.pm, which doesn't hurt, because it is only the
# name of the program running. For other hook events and variables,
# there might be vital data in one of the references. Be very careful
# before changing values willy-nilly.
$$nameref =~ s/name/blame/;
}
register_hook('startup', \&print_banner0);
sub print_banner1 {
my ($ns, $nameref, $verref, $confref, $suptagsref, $argvref) = @_;
# Since $NAME used to be 'arename', the substitution
# in print_banner0() will have changed $NAME to 'areblame',
# which $$nameref below will reveal.
print "ANOTHER BANNER! $$nameref $$verref\n";
}
register_hook('startup', \&print_banner1);
After that short introduction, here is something more useful. The following
hook will replace all whitespace with underscores in generated file names.
sub replace_spaces_by_underscore {
my ($templateref, $datref) = @_;
$$templateref =~ s/\s+/_/g;
}
register_hook('post_expand_template', \&replace_spaces_by_underscore);
This will do the trick, but there is actually an B<arename> extension that is
distributed with the application, which is designed to solve exactly this
problem. See L</EXTENSIONS> below for details on the `B<ReplaceSpaces>'
extension module.
=head1 EXTENSIONS
B<Arename> comes with a number of extensions implemented as Perl modules, to
solve a number of more exotic tasks, that are not addressed within the core
Module `ARename.pm'.
All of these bundled extension modules (which are all children of the `ARename'
namespace) are fully documented within their source files and is accessible by
the `B<perldoc>' utility:
% perldoc ARename::ReplaceSpaces
Modules, that implement a hook all feature a convenience subroutine
`B<register()>', which registers the hook code to the event the author
intended. For example, to use the `B<RenameSpaces>' hook, add the following to
your hooks file:
use ARename::ReplaceSpaces;
ARename::ReplaceSpaces::register();
Here is a list of bundled extensions:
=over 4
=item B<BailOut>
This is a hook, to terminate B<arename> after reading all configuration files.
It is designed to help with testing new settings and is probably not very
useful for the average user.
=item B<KillNonASCII>
This module implements a hook that removes all non-ascii characters from
generated file names.
This is also the extension module you want look at, if you are interested in
writing your own extension modules. It features all code and documentation,
that is required of an extension to make it into the B<arename> package.
=item B<MP3RecodeToUTF8>
`B<MP3RecodeToUTF8>' is a hook that attempts to cure problems caused by the
different types of mp3 tag versions and the encoding mess that comes along with
it.
If you are on an UTF-8 based system and wonder why B<arename> produces latin1
characters for mp3 files, that have non-ascii characters in their tags, this
extension may be of help.
=item B<RemoveEmptySubdirs>
This module tries to remove empty directories that might have emerged due to
files being moved to another directory in the renaming process.
=item B<ReplaceSpaces>
This is a hook that replaces whitespace in generated filenames by a configurable
string, which defaults to a single underscore character B<"_">.
=item B<Template::Albumless>
Implements a hook to handle tracks with missing `album' tags, by offering to
switch to an entirely different template for these files.
=item B<TNPadAdjustByAlbum>
This module allows one to adjust the value of the `I<tnpad>' core setting based on
patterns that are matched against a track's `album' tag.
The idea is to have proper padding the large audiobooks that contain more than
99 tracks.
=back
There are a few utility modules, that implement helpful code that is shared
among all bundled extension modules. Some of the code may be useful to user
defined hooks or extension modules, too.
=over 4
=item B<Util::Files>
This is a module that contains file-related utilities.
=item B<Util::IsNumber>
The purpose of this module is to provide helper subroutines, which check if
values look like numbers (integers, unsigned integers, etc.).
=item B<Util::RegisterModuleHook>
This implements a helper to quickly create the `I<register()>' subroutine of
hook extension modules.
=item B<Util::VersionGuard>
This module implements a subroutine, that is designed to detect version
discrepancies between an extension module and the `ARename.pm' core module.
=back
=head2 User-defined Extensions
Say you have decided, that the `I<ARename::Extension::register()>' idea to
encapsulate extensions is a good idea and now you want to do that yourself,
too. Maybe because, you just like to keep your `hooks' file tidy or maybe
because you want to contribute your awesome extension code back to
B<arename>. Either way, you will need a place to put your Perl code.
B<Arename> does B<NOT> set such a place by default. But it is very easy to set
it yourself from the `hooks' file:
BEGIN {
unshift @INC, $ENV{HOME} . q{/.arename};
}
That way you can place Perl modules into `I<~/.arename>' like this:
~/.arename/ARename/MyAwesomeExtension.pm
And then just use it like the bundled extensions:
use ARename::MyAwesomeExtension.pm;
ARename::MyAwesomeExtension::register();
Take a look at the `B<KillNonASCII.pm.in>' file in the `B<arename>' sources,
for details about how to write proper extensions and how to make them
configurable and how to make use of the bundled utilities to make your
extension appropriate for inclusion with `B<arename>'.
=head1 SEE ALSO
B<find(1)>, B<xargs(1)>, B<perldoc(1)>, B<Audio::Scan>.
B<ARename::BailOut>, B<ARename::KillNonASCII>,
B<ARename::MP3RecodeToUTF8>, B<ARename::RemoveEmptySubdirs>,
B<ARename::ReplaceSpaces>, B<ARename::TNPadAdjustByAlbum>.
B<ARename::Template::Albumless>
B<ARename::Util::Files>, B<ARename::Util::IsNumber>,
B<ARename::Util::RegisterModuleHook>, B<ARename::Util::VersionGuard>.
=head1 VERSION
This manual describes B<arename> version I<@@arenameversioninfo@@>.
=head1 AUTHOR
Frank Terbeck E<lt>ft@bewatermyfriend.orgE<gt>,
Please report bugs.
=head1 LICENCE
Copyright 2007-2017
Frank Terbeck <ft@bewatermyfriend.org>, All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above
copyright notice, this list of conditions and the following
disclaimer.
2. Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS OF THE
PROJECT BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=cut
my ( $NAME, $VERSION ) = qw( arename @@arenameversioninfo@@ );
# Initialisation
ARename::set_nameversion($NAME, $VERSION);
ARename::set_default_options();
ARename::read_cmdline_options();
ARename::read_rcs();
ARename::read_cmdline_options_late();
if (ARename::cmdopts('S')) {
ARename::dump_profiles();
exit 0;
}
if (ARename::cmdopts('L')) {
ARename::dump_config();
exit 0;
}
ARename::read_hook_files();
ARename::startup_hook();
# status messages and cosmetics
if (ARename::get_opt('checktemplatesinitially')) {
my $err = 0;
ARename::op('newline');
foreach my $t (ARename::get_opt_from_everywhere('template')) {
ARename::op('check-template', $t);
if (ARename::template_deep_inspect($t) < 1) {
$err++;
ARename::op('error-template', $t);
}
}
foreach my $t (ARename::get_opt_from_everywhere('comp_template')) {
ARename::op('check-comp-template', $t);
if (ARename::template_deep_inspect($t) < 1) {
$err++;
ARename::op('error-comp-template', $t);
}
}
if ($err) {
ARename::op('newline');
ARename::op('error-any-template');
exit 1;
}
};
if (!ARename::get_opt('load_quiet')) {
ARename::op('newline');
ARename::op('dryrun') if (ARename::get_opt("dryrun"));
ARename::op('copymode') if (ARename::get_opt("copymode"));
my $v = ARename::get_opt("verbosity");
ARename::op('suppress-skips') if (ARename::get_opt("suppress_skips"));
ARename::op('verbosity', $v) if ($v > 5);
ARename::op('readstdin') if (ARename::get_opt("readstdin"));
ARename::op('newline');
}
foreach my $file (@ARGV) {
ARename::set_file($file);
ARename::process_file($file);
}
if (ARename::get_opt("readstdin")) {
while (<STDIN>) { ## no critic (ProhibitExplicitStdin)
# *STDIN should be the right thing to do here.
chomp;
ARename::set_file($_);
ARename::process_file($_);
}
}
ARename::run_hook('normal_quit', \@ARGV);
|