nodetouch.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. #!/usr/bin/env node
  2. const touch = require("../index.js")
  3. const usage = code => {
  4. console[code ? 'error' : 'log'](
  5. 'usage:\n' +
  6. 'touch [-acfm] [-r file] [-t [[CC]YY]MMDDhhmm[.SS]] file ...'
  7. )
  8. process.exit(code)
  9. }
  10. const singleFlags = {
  11. a: 'atime',
  12. m: 'mtime',
  13. c: 'nocreate',
  14. f: 'force'
  15. }
  16. const singleOpts = {
  17. r: 'ref',
  18. t: 'time'
  19. }
  20. const files = []
  21. const args = process.argv.slice(2)
  22. const options = {}
  23. for (let i = 0; i < args.length; i++) {
  24. const arg = args[i]
  25. if (!arg.match(/^-/)) {
  26. files.push(arg)
  27. continue
  28. }
  29. // expand shorthands
  30. if (arg.charAt(1) !== '-') {
  31. const expand = []
  32. for (let f = 1; f < arg.length; f++) {
  33. const fc = arg.charAt(f)
  34. const sf = singleFlags[fc]
  35. const so = singleOpts[fc]
  36. if (sf)
  37. expand.push('--' + sf)
  38. else if (so) {
  39. const soslice = arg.slice(f + 1)
  40. const soval = soslice.charAt(0) === '=' ? soslice : '=' + soslice
  41. expand.push('--' + so + soval)
  42. f = arg.length
  43. } else if (arg !== '-' + fc)
  44. expand.push('-' + fc)
  45. }
  46. if (expand.length) {
  47. args.splice.apply(args, [i, 1].concat(expand))
  48. i--
  49. continue
  50. }
  51. }
  52. const argsplit = arg.split('=')
  53. const key = argsplit.shift().replace(/^\-\-/, '')
  54. const val = argsplit.length ? argsplit.join('=') : null
  55. switch (key) {
  56. case 'time':
  57. const timestr = val || args[++i]
  58. // [-t [[CC]YY]MMDDhhmm[.SS]]
  59. const parsedtime = timestr.match(
  60. /^(([0-9]{2})?([0-9]{2}))?([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})(\.([0-9]{2}))?$/
  61. )
  62. if (!parsedtime) {
  63. console.error('touch: out of range or illegal ' +
  64. 'time specification: ' +
  65. '[[CC]YY]MMDDhhmm[.SS]')
  66. process.exit(1)
  67. } else {
  68. const y = +parsedtime[1]
  69. const year = parsedtime[2] ? y
  70. : y <= 68 ? 2000 + y
  71. : 1900 + y
  72. const MM = +parsedtime[4] - 1
  73. const dd = +parsedtime[5]
  74. const hh = +parsedtime[6]
  75. const mm = +parsedtime[7]
  76. const ss = +parsedtime[8]
  77. options.time = new Date(Date.UTC(year, MM, dd, hh, mm, ss))
  78. }
  79. continue
  80. case 'ref':
  81. options.ref = val || args[++i]
  82. continue
  83. case 'mtime':
  84. case 'nocreate':
  85. case 'atime':
  86. case 'force':
  87. options[key] = true
  88. continue
  89. default:
  90. console.error('touch: illegal option -- ' + arg)
  91. usage(1)
  92. }
  93. }
  94. if (!files.length)
  95. usage()
  96. process.exitCode = 0
  97. Promise.all(files.map(f => touch(f, options)))
  98. .catch(er => process.exitCode = 1)