【问题标题】:delete and copy files using shx in package.json使用 package.json 中的 shx 删除和复制文件
【发布时间】:2023-03-24 03:24:02
【问题描述】:

我有两个 npm 项目,一个是 Gatsby 项目,名为 web-project,另一个是 Express 项目,名为 server-project

这是项目的文件结构:

- projects
   - web-project
      - public
      - package.json
   - server-project
      - package.json
      - public

如果我在web-project/package.json 中运行命令npm run build,我想为网络项目生成构建文件,删除文件夹server-project/public 中的内容并将内容从web-project/public 复制到server-project/public

我尝试使用shx,它在本地安装在web-project,但它不起作用。 Gatsby 生成构建文件,但 shx 不复制它们。

web-project/package.json

"scripts": {
    "build": "gatsby build && (shx find ../server-project/public -type f -delete && shx cp -R public/* ../server-project/public)"
    ...
  },

npm 调试日志文件:

0 info it worked if it ends with ok
1 verbose cli [
1 verbose cli   '/usr/local/Cellar/node/12.1.0/bin/node',
1 verbose cli   '/usr/local/bin/npm',
1 verbose cli   'run',
1 verbose cli   'build'
1 verbose cli ]
2 info using npm@6.9.0
3 info using node@v12.1.0
4 verbose run-script [ 'prebuild', 'build', 'postbuild' ]
5 info lifecycle tau@1.0.0~prebuild: tau@1.0.0
6 info lifecycle tau@1.0.0~build: tau@1.0.0
7 verbose lifecycle tau@1.0.0~build: unsafe-perm in lifecycle true
8 verbose lifecycle tau@1.0.0~build: PATH: /usr/local/lib/node_modules/npm/node_modules/npm-lifecycle/node-gyp-bin:/Users/and/devel/tau/web-project/node_modules/.bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
9 verbose lifecycle tau@1.0.0~build: CWD: /Users/and/devel/tau/web-project
10 silly lifecycle tau@1.0.0~build: Args: [
10 silly lifecycle   '-c',
10 silly lifecycle   'gatsby build && (shx find ../server-project/public -type ' +
10 silly lifecycle     'f -delete && shx cp -R public/* ../server-project/public)'
10 silly lifecycle ]
11 silly lifecycle tau@1.0.0~build: Returned: code: 1  signal: null
12 info lifecycle tau@1.0.0~build: Failed to exec build script
13 verbose stack Error: tau@1.0.0 build: `gatsby build && (shx find ../server-project/public -type f -delete && shx cp -R public/* ../server-project/public)`
13 verbose stack Exit status 1
13 verbose stack     at EventEmitter.<anonymous> (/usr/local/lib/node_modules/npm/node_modules/npm-lifecycle/index.js:301:16)
13 verbose stack     at EventEmitter.emit (events.js:196:13)
13 verbose stack     at ChildProcess.<anonymous> (/usr/local/lib/node_modules/npm/node_modules/npm-lifecycle/lib/spawn.js:55:14)
13 verbose stack     at ChildProcess.emit (events.js:196:13)
13 verbose stack     at maybeClose (internal/child_process.js:1000:16)
13 verbose stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:267:5)
14 verbose pkgid tau@1.0.0
15 verbose cwd /Users/and/devel/tau/web-project
16 verbose Darwin 18.7.0
17 verbose argv "/usr/local/Cellar/node/12.1.0/bin/node" "/usr/local/bin/npm" "run" "build"
18 verbose node v12.1.0
19 verbose npm  v6.9.0
20 error code ELIFECYCLE
21 error errno 1
22 error tau@1.0.0 build: `gatsby build && (shx find ../server-project/public -type f -delete && shx cp -R public/* ../server-project/public)`
22 error Exit status 1
23 error Failed at the tau@1.0.0 build script.
23 error This is probably not a problem with npm. There is likely additional logging output above.
24 verbose exit [ 1, true ]

我尝试将构建命令更改为仅将文件从一个文件夹复制到另一个文件夹:

web-project/package.json

{
  "name": "tau",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "develop": "gatsby develop",
    "build": "shx cp -R public/* ../server-project/public",
    "serve": "gatsby serve",
    "start": "node server.js",
    "gh-pages": "gatsby build --prefix-paths && gh-pages -d public",
    "lint": "eslint src --fix",
    "dev": "(shx --silent rm -rf public .cache || shx true) && gatsby develop",
    "server": "cross-env NODE_ENV=development DEBUG=api nodemon server.js"
  },
  "author": "PI",
  "license": "MIT",
  "dependencies": {
    "@fortawesome/fontawesome-svg-core": "^1.2.25",
    "@fortawesome/free-brands-svg-icons": "^5.12.0",
    "@fortawesome/free-solid-svg-icons": "^5.11.2",
    "@fortawesome/react-fontawesome": "^0.1.7",
    "@kunukn/react-collapse": "1",
    "@material-ui/core": "^4.9.5",
    "@popperjs/core": "^2.3.3",
    "add": "^2.0.6",
    "axios": "^0.19.0",
    "basic-auth": "^2.0.1",
    "bootstrap": "4.2.1",
    "chart.js": "^2.9.3",
    "d3-node": "^2.2.1",
    "debug": "^4.1.1",
    "font-awesome": "4.7.0",
    "framer-motion": "^1.10.3",
    "gatsby": "^2.18.12",
    "gatsby-plugin-canonical-urls": "^2.3.0",
    "gatsby-plugin-dark-mode": "^1.1.0",
    "gatsby-source-prismic-graphql": "^3.5.0",
    "gatsby-transformer-remark": "^2.6.53",
    "lodash.get": "^4.4.2",
    "lodash.groupby": "^4.6.0",
    "lodash.pickby": "^4.6.0",
    "marked": "^0.8.0",
    "moment": "^2.24.0",
    "prismic-reactjs": "^1.3.1",
    "prop-types": "^15.7.2",
    "react-chartjs-2": "^2.8.0",
    "react-collapsible": "^2.6.3",
    "react-d3-components": "^0.9.1",
    "react-d3-library": "^1.1.8",
    "react-headroom": "^3.0.0",
    "react-helmet": "^5.2.0",
    "react-lazyload": "^2.6.5",
    "react-moment": "^0.9.6",
    "react-onclickout": "^2.0.8",
    "react-popper": "^2.2.3",
    "react-popper-tooltip": "^2.11.1",
    "react-responsive": "^8.0.1",
    "react-scroll-to": "^3.0.0-beta.3",
    "react-sidebar": "^3.0.2",
    "react-slick": "^0.25.2",
    "react-svg-donuts": "^1.0.0",
    "react-telegram-embed": "^0.0.10",
    "react-toastify": "^5.4.1",
    "react-twitter-embed": "^3.0.3",
    "react-window": "^1.8.5",
    "reactstrap": "^8.4.1",
    "slick-carousel": "^1.8.1",
    "underscore": "^1.9.1",
    "yarn": "^1.21.1"
  },
  "devDependencies": {
    "@prototype-interactive/eslint-config": "^0.1.1",
    "autoprefixer": "^9.4.4",
    "dotenv": "^8.2.0",
    "eslint": "^5.12.0",
    "gatsby-plugin-google-analytics": "^2.3.0",
    "gatsby-plugin-postcss": "^2.0.2",
    "gatsby-plugin-postcss-sass": "^1.0.22",
    "gatsby-plugin-react-helmet": "^3.0.5",
    "gatsby-plugin-sass": "^2.0.7",
    "gatsby-source-filesystem": "^2.2.2",
    "gatsby-transformer-json": "^2.1.7",
    "gh-pages": "^2.0.1",
    "husky": "^1.3.1",
    "prettier": "^1.15.3",
    "pretty-quick": "^1.8.0",
    "react": "^16.7.0",
    "react-dom": "^16.7.0",
    "shx": "^0.3.2",
    "svg-sprite-loader": "^4.1.3"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/PI/gatsby-react-boilerplate.git"
  },
  "bugs": {
    "url": "https://github.com/PI/gatsby-react-boilerplate/issues"
  },
  "homepage": "https://github.com/PI/gatsby-react-boilerplate#readme"
}

npm 调试日志文件:

0 info it worked if it ends with ok
1 verbose cli [
1 verbose cli   '/usr/local/Cellar/node/12.1.0/bin/node',
1 verbose cli   '/usr/local/bin/npm',
1 verbose cli   'run',
1 verbose cli   'build'
1 verbose cli ]
2 info using npm@6.9.0
3 info using node@v12.1.0
4 verbose run-script [ 'prebuild', 'build', 'postbuild' ]
5 info lifecycle tau@1.0.0~prebuild: tau@1.0.0
6 info lifecycle tau@1.0.0~build: tau@1.0.0
7 verbose lifecycle tau@1.0.0~build: unsafe-perm in lifecycle true
8 verbose lifecycle tau@1.0.0~build: PATH: /usr/local/lib/node_modules/npm/node_modules/npm-lifecycle/node-gyp-bin:/Users/and/devel/tau/web-project/node_modules/.bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
9 verbose lifecycle tau@1.0.0~build: CWD: /Users/and/devel/tau/web-project
10 silly lifecycle tau@1.0.0~build: Args: [ '-c', 'shx cp -R public/* ../web-project-project/public' ]
11 silly lifecycle tau@1.0.0~build: Returned: code: 1  signal: null
12 info lifecycle tau@1.0.0~build: Failed to exec build script
13 verbose stack Error: tau@1.0.0 build: `shx cp -R public/* ../web-project-project/public`
13 verbose stack Exit status 1
13 verbose stack     at EventEmitter.<anonymous> (/usr/local/lib/node_modules/npm/node_modules/npm-lifecycle/index.js:301:16)
13 verbose stack     at EventEmitter.emit (events.js:196:13)
13 verbose stack     at ChildProcess.<anonymous> (/usr/local/lib/node_modules/npm/node_modules/npm-lifecycle/lib/spawn.js:55:14)
13 verbose stack     at ChildProcess.emit (events.js:196:13)
13 verbose stack     at maybeClose (internal/child_process.js:1000:16)
13 verbose stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:267:5)
14 verbose pkgid tau@1.0.0
15 verbose cwd /Users/and/devel/tau/web-project
16 verbose Darwin 18.7.0
17 verbose argv "/usr/local/Cellar/node/12.1.0/bin/node" "/usr/local/bin/npm" "run" "build"
18 verbose node v12.1.0
19 verbose npm  v6.9.0
20 error code ELIFECYCLE
21 error errno 1
22 error tau@1.0.0 build: `shx cp -R public/* ../web-project-project/public`
22 error Exit status 1
23 error Failed at the tau@1.0.0 build script.
23 error This is probably not a problem with npm. There is likely additional logging output above.
24 verbose exit [ 1, true ]

【问题讨论】:

  • 去掉--silent再试试,这样至少能看到错误
  • @TarunLalwani 我删除了--silent 并用新的日志文件更新了问题
  • 你试过把它分成几部分吗?首先运行gatsby build,然后独立运行2 个shx 命令,看看你得到了什么?另外,您是否在全局或本地安装了shx
  • 正如@ChristosLytras 提到的,您需要将命令分解为 3 个命令并一一运行,以了解实际中断的命令。它可能是构建本身。
  • @ChristosLytras shx 安装在本地,是的,我确实尝试将命令分成几部分,但错误消息没有帮助。我编辑了我的问题并添加了 npm 日志文件。

标签: node.js unix npm gatsby npm-scripts


【解决方案1】:

这部分存在的主要问题:

shx find ../server-project/public -type f -delete

shx 不支持-type f 标志(请参阅issue #177)。据推测,-delete 标志也不支持。

考虑用执行以下操作的 node.js 脚本替换该部分:

  1. 利用shelljs find 方法。
  2. 使用forEach() 迭代找到的路径名数组。
  3. forEach 回调的主体中检查它是否是一个文件并相应地删除。

例如,将其完全放入一个名为 build 的单个 npm 脚本中:

"scripts": {
  ...
  "build": "gatsby build && node -e \"var sh = require('shelljs'), fs = require('fs'); sh.find('../server-project/public').forEach(function (file) { if (!fs.statSync(file).isDirectory()) { sh.rm(file); }});\" && shx cp -R \"public\" \"../server-project/public\""
  ...
}

注意事项:

  1. 您在 OP 中尝试使用 find ../server-project/public -type f -delete 意味着您的意图是(仅)删除 ../server-project/public 中的所有文件(n 级深) - 但不要删除../server-project/public 中的任何文件夹(再次 n 层深)。这就是上述示例中的node -e \"...\" 命令所复制的内容。

  2. nodejs 命令行选项-e 用于评估内联Javascript,本质上是这样的:

    var sh = require('shelljs'),
        fs = require('fs');
    
    sh.find('../server-project/public').forEach(function (file) {
        if (!fs.statSync(file).isDirectory()) {
            sh.rm(file);
        }
    });
    
  3. 您最终的 shx cp -R ... 命令中的 globstar (*) 以及包含复合命令的括号 (...) 已被省略。

【讨论】:

    【解决方案2】:

    您可以从shx cp -R public/* ../server-project/public 中删除通配符,因为递归标志将拾取源目录中的所有内容。这应该让你得到你所追求的 -

    shx cp -R public ../server-project/public
    

    【讨论】:

    • 谢谢,我发现这个命令失败了find ../server-project/public -type f -delete。我只是简单地尝试了shx rm ../server-project/public/*,但它也失败了。
    【解决方案3】:

    看起来您已经在构建系统中使用了find。我利用 tar 并在我维护的一些构建系统中大量发现,这对我来说效果很好。 tar 可以很好地处理各种各样的边缘情况,因为它最初是作为备份实用程序编写的。

    在 tar 中,- 是文件名,表示标准输入或标准输出,-T 指定要备份的文件列表,-C 指定其工作目录。这使您可以将一堆东西与管道粘合在一起,并完成一些非常酷的东西。例如,

    (cd /path/to/src/files && find . -type f -name) \
    | tar -T - -cf - \
    | tar -C /path/to/dest -xvf -
    
    • 子shell 让我可以在不影响其他命令的情况下找到目录
    • find 在标准输出上生成文件列表
    • 第一个 tar 读取要在标准输入上存档的文件列表
    • 第一个 tar 在标准输出上生成存档
    • 第二个 tar 将目录更改为 /path/to/dest
    • 然后它在标准输入上提取存档
    • 并且 'v' 打印它在提取时提取的文件列表

    这将为您保留所有权、组成员资格、权限、符号链接、目录结构,以及整个九码。即使是带空格的文件名也不会搞砸。 :)

    【讨论】:

    • 有趣。我发现这个命令失败了find ../server-project/public -type f -delete。我只是简单地尝试了shx rm ../server-project/public/*,但它也失败了。
    猜你喜欢
    • 2017-01-17
    • 2013-03-04
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-03
    • 1970-01-01
    相关资源
    最近更新 更多