pymdkit 1.5.3__tar.gz → 1.5.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. {pymdkit-1.5.3 → pymdkit-1.5.4}/PKG-INFO +8 -7
  2. {pymdkit-1.5.3 → pymdkit-1.5.4}/README.md +7 -6
  3. {pymdkit-1.5.3 → pymdkit-1.5.4}/pyproject.toml +1 -1
  4. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/__init__.py +1 -1
  5. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/_cifio.py +1 -1
  6. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/gpumd_msd.py +26 -8
  7. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/realloc_occ.py +7 -7
  8. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit.egg-info/PKG-INFO +8 -7
  9. {pymdkit-1.5.3 → pymdkit-1.5.4}/LICENSE +0 -0
  10. {pymdkit-1.5.3 → pymdkit-1.5.4}/setup.cfg +0 -0
  11. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/__init__.py +0 -0
  12. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/_extxyz.py +0 -0
  13. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/_fileio.py +0 -0
  14. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/_geometry.py +0 -0
  15. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/_gpumd.py +0 -0
  16. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/_precision.py +0 -0
  17. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/_reduction.py +0 -0
  18. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/_vasp_output.py +0 -0
  19. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/_vaspset.py +0 -0
  20. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/add_config_type.py +0 -0
  21. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/chemsys_entry.py +0 -0
  22. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/compute_ehull.py +0 -0
  23. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/compute_rmsd.py +0 -0
  24. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/convert.py +0 -0
  25. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/ewald.py +0 -0
  26. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/gather_fs.py +0 -0
  27. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/gpumd_group.py +0 -0
  28. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/gpumd_relax.py +0 -0
  29. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/gpumd_thermo.py +0 -0
  30. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/gpumd_trjcat.py +0 -0
  31. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/nep_rmse.py +0 -0
  32. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/pca.py +0 -0
  33. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/perturb.py +0 -0
  34. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/submit_vasp.py +0 -0
  35. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/substitute.py +0 -0
  36. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/supercell.py +0 -0
  37. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/symmetrize.py +0 -0
  38. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/trj_extract.py +0 -0
  39. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/trj_sparse.py +0 -0
  40. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/umap.py +0 -0
  41. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/vasp2xyz.py +0 -0
  42. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/vasp_fe.py +0 -0
  43. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/vasp_relax.py +0 -0
  44. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/commands/vasp_static.py +0 -0
  45. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit/pymdkit_main.py +0 -0
  46. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit.egg-info/SOURCES.txt +0 -0
  47. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit.egg-info/dependency_links.txt +0 -0
  48. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit.egg-info/entry_points.txt +0 -0
  49. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit.egg-info/requires.txt +0 -0
  50. {pymdkit-1.5.3 → pymdkit-1.5.4}/src/pymdkit.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pymdkit
3
- Version: 1.5.3
3
+ Version: 1.5.4
4
4
  Summary: A unified command-line toolkit for atomistic / MD structure workflows.
5
5
  Author-email: Yueda Wang <ydwang0608@ustc.edu.cn>
6
6
  License-Expression: GPL-3.0-or-later
@@ -136,7 +136,7 @@ pmk submit-vasp -subscript sub_vasp -queue slurm -max-job-num 30
136
136
  nohup pmk submit-vasp -subscript sub_vasp -queue slurm -max-job-num 30 > submit-vasp.log 2>&1 &
137
137
  pmk realloc-occ -i 66-Li4YCl6-5.cif -of chg-balance -formula Li3YCl6
138
138
  pmk realloc-occ -if cifs -of chg-balance -formula Li3YCl6
139
- pmk realloc-occ -i 66-Li4YCl6-5.cif -of chg-balance -formula Li3YCl6 -occ 0 0.25 0.5 0.75 1
139
+ pmk realloc-occ -i 66-Li4YCl6-5.cif -of chg-balance -formula Li3YCl6 -occ 0 0.125 0.25 0.375 0.5 0.625 0.75 0.875 1
140
140
  pmk substitute -i Li3YCl6.cif -se Li -sn 3 -we Na -wn 3 -on 100
141
141
  pmk substitute -i Li3YCl6.cif -se Li -sn 3 -we none -on 100
142
142
  pmk substitute -i Li96Ta6La11Cl72.cif -se Li1 Li2 -sn 20 67 -we none -on 100
@@ -214,8 +214,9 @@ the last 50% of the SDC correlation-time range, converts A^2/ps to cm^2/s by
214
214
  multiplying by `1e-4`, and reports `D_total = (D_x + D_y + D_z) / 3`.
215
215
  Each job receives `msd/group_INDEX_ELEMENT_TEMP_msd.txt`, a matching `_sdc.txt`,
216
216
  and a `_results.txt`. The root receives a compact `sigma-sdc-summary.txt` with
217
- one row per job folder. Conductivities use two decimal places; diffusion
218
- coefficients use compact scientific notation with two decimal places. If the
217
+ one fixed-width, right-aligned row per job folder. Conductivities use two
218
+ decimal places; diffusion coefficients use compact scientific notation with
219
+ two decimal places. If the
219
220
  mobile ion occupies multiple groups, conductivities are summed and diffusion
220
221
  coefficients are particle-count-weighted.
221
222
 
@@ -237,8 +238,8 @@ Wyckoff labels, and CIF layout. Every input receives `OUTPUT/INPUT_STEM/`; for
237
238
  the supplied Li4YCl6 example, the two outputs are `...-d1.cif` with `Li1=0.50`
238
239
  and `...-d2.cif` with `Li2=0.50`. Folder mode uses `-if` with the same `-of` and
239
240
  `-formula` options. Add `-occ` followed by the only permitted occupancy values;
240
- for example, `-occ 0 0.25 0.5 0.75 1` also permits the valid allocation
241
- `Li1=0.75, Li2=0.75`.
241
+ three decimal places are supported, so grids containing `0.125`, `0.375`,
242
+ `0.625`, and `0.875` are preserved exactly in generated CIF files.
242
243
 
243
244
  `gather-fs` recursively scans all job folders below the current directory. For
244
245
  VASP it follows the global `vaspout.h5 > vasprun.xml > OUTCAR` priority and
@@ -305,7 +306,7 @@ and `Cl`. Oxidation numbers remain in the separate
305
306
 
306
307
  Newly serialized floating-point values use eight digits after the decimal
307
308
  point across PMK structure, trajectory, data, report, and screen output. CIF
308
- `_atom_site_occupancy` values use two digits and
309
+ `_atom_site_occupancy` values use three digits and
309
310
  `_atom_type_oxidation_number` values use one digit. In extended XYZ, zero components
310
311
  inside the second-line `Lattice="..."` value remain `0.0`; other generated
311
312
  floating-point values use eight digits. Commands that select or concatenate
@@ -109,7 +109,7 @@ pmk submit-vasp -subscript sub_vasp -queue slurm -max-job-num 30
109
109
  nohup pmk submit-vasp -subscript sub_vasp -queue slurm -max-job-num 30 > submit-vasp.log 2>&1 &
110
110
  pmk realloc-occ -i 66-Li4YCl6-5.cif -of chg-balance -formula Li3YCl6
111
111
  pmk realloc-occ -if cifs -of chg-balance -formula Li3YCl6
112
- pmk realloc-occ -i 66-Li4YCl6-5.cif -of chg-balance -formula Li3YCl6 -occ 0 0.25 0.5 0.75 1
112
+ pmk realloc-occ -i 66-Li4YCl6-5.cif -of chg-balance -formula Li3YCl6 -occ 0 0.125 0.25 0.375 0.5 0.625 0.75 0.875 1
113
113
  pmk substitute -i Li3YCl6.cif -se Li -sn 3 -we Na -wn 3 -on 100
114
114
  pmk substitute -i Li3YCl6.cif -se Li -sn 3 -we none -on 100
115
115
  pmk substitute -i Li96Ta6La11Cl72.cif -se Li1 Li2 -sn 20 67 -we none -on 100
@@ -187,8 +187,9 @@ the last 50% of the SDC correlation-time range, converts A^2/ps to cm^2/s by
187
187
  multiplying by `1e-4`, and reports `D_total = (D_x + D_y + D_z) / 3`.
188
188
  Each job receives `msd/group_INDEX_ELEMENT_TEMP_msd.txt`, a matching `_sdc.txt`,
189
189
  and a `_results.txt`. The root receives a compact `sigma-sdc-summary.txt` with
190
- one row per job folder. Conductivities use two decimal places; diffusion
191
- coefficients use compact scientific notation with two decimal places. If the
190
+ one fixed-width, right-aligned row per job folder. Conductivities use two
191
+ decimal places; diffusion coefficients use compact scientific notation with
192
+ two decimal places. If the
192
193
  mobile ion occupies multiple groups, conductivities are summed and diffusion
193
194
  coefficients are particle-count-weighted.
194
195
 
@@ -210,8 +211,8 @@ Wyckoff labels, and CIF layout. Every input receives `OUTPUT/INPUT_STEM/`; for
210
211
  the supplied Li4YCl6 example, the two outputs are `...-d1.cif` with `Li1=0.50`
211
212
  and `...-d2.cif` with `Li2=0.50`. Folder mode uses `-if` with the same `-of` and
212
213
  `-formula` options. Add `-occ` followed by the only permitted occupancy values;
213
- for example, `-occ 0 0.25 0.5 0.75 1` also permits the valid allocation
214
- `Li1=0.75, Li2=0.75`.
214
+ three decimal places are supported, so grids containing `0.125`, `0.375`,
215
+ `0.625`, and `0.875` are preserved exactly in generated CIF files.
215
216
 
216
217
  `gather-fs` recursively scans all job folders below the current directory. For
217
218
  VASP it follows the global `vaspout.h5 > vasprun.xml > OUTCAR` priority and
@@ -278,7 +279,7 @@ and `Cl`. Oxidation numbers remain in the separate
278
279
 
279
280
  Newly serialized floating-point values use eight digits after the decimal
280
281
  point across PMK structure, trajectory, data, report, and screen output. CIF
281
- `_atom_site_occupancy` values use two digits and
282
+ `_atom_site_occupancy` values use three digits and
282
283
  `_atom_type_oxidation_number` values use one digit. In extended XYZ, zero components
283
284
  inside the second-line `Lattice="..."` value remain `0.0`; other generated
284
285
  floating-point values use eight digits. Commands that select or concatenate
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pymdkit"
7
- version = "1.5.3"
7
+ version = "1.5.4"
8
8
  description = "A unified command-line toolkit for atomistic / MD structure workflows."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -1,3 +1,3 @@
1
1
  """pymdkit -- a unified CLI for atomistic / MD structure workflows."""
2
2
 
3
- __version__ = "1.5.3"
3
+ __version__ = "1.5.4"
@@ -198,7 +198,7 @@ def _format_cif_scalar(value, precision, force=False):
198
198
  def _format_cif_numbers(block):
199
199
  for tag, value in list(block.data.items()):
200
200
  if tag == OCCUPANCY_TAG:
201
- precision = 2
201
+ precision = 3
202
202
  elif tag == OXIDATION_TAG:
203
203
  precision = 1
204
204
  else:
@@ -402,13 +402,7 @@ def write_summary(root, records, diffuse_ion):
402
402
  "sigma_y(mS/cm)", "sigma_z(mS/cm)", "D_total(cm^2/s)",
403
403
  "D_x(cm^2/s)", "D_y(cm^2/s)", "D_z(cm^2/s)",
404
404
  ]
405
- lines = [
406
- "GPUMD SDC and Nernst-Einstein conductivity summary",
407
- f"Mobile ion: {diffuse_ion}",
408
- "SDC average: arithmetic mean over the last 50% of correlation time",
409
- "\t".join(columns),
410
- "-" * len("\t".join(columns).expandtabs(4)),
411
- ]
405
+ rows = []
412
406
  jobs = {}
413
407
  for record in records:
414
408
  if record["element"] == diffuse_ion and record["conductivity"] is not None:
@@ -425,7 +419,31 @@ def write_summary(root, records, diffuse_ion):
425
419
  *(_compact_scientific(diffusion[index])
426
420
  for index in (3, 0, 1, 2)),
427
421
  ]
428
- lines.append("\t".join(fields))
422
+ rows.append(fields)
423
+ widths = [
424
+ max(len(columns[index]), *(len(row[index]) for row in rows))
425
+ for index in range(len(columns))
426
+ ]
427
+ header = " ".join(
428
+ f"{column:<{widths[index]}}" if index == 0
429
+ else f"{column:>{widths[index]}}"
430
+ for index, column in enumerate(columns)
431
+ )
432
+ lines = [
433
+ "GPUMD SDC and Nernst-Einstein conductivity summary",
434
+ f"Mobile ion: {diffuse_ion}",
435
+ "SDC average: arithmetic mean over the last 50% of correlation time",
436
+ header,
437
+ "-" * len(header),
438
+ ]
439
+ lines.extend(
440
+ " ".join(
441
+ f"{value:<{widths[index]}}" if index == 0
442
+ else f"{value:>{widths[index]}}"
443
+ for index, value in enumerate(row)
444
+ )
445
+ for row in rows
446
+ )
429
447
  (Path(root) / SUMMARY_FILE).write_text(
430
448
  "\n".join(lines) + "\n", encoding="utf-8")
431
449
 
@@ -253,9 +253,9 @@ def _normalize_occupancies(values):
253
253
  number = float(value)
254
254
  if not -TOLERANCE <= number <= 1.0 + TOLERANCE:
255
255
  raise ValueError("-occ values must be between 0 and 1")
256
- rounded = round(number, 2)
256
+ rounded = round(number, 3)
257
257
  if abs(number - rounded) > TOLERANCE:
258
- raise ValueError("-occ values support at most two decimal places")
258
+ raise ValueError("-occ values support at most three decimal places")
259
259
  occupancies.append(min(1.0, max(0.0, rounded)))
260
260
  result = tuple(sorted(set(occupancies)))
261
261
  if not result:
@@ -302,7 +302,7 @@ def _grid_occupancy_options(sites, target_count, allowed_occupancies):
302
302
  values,
303
303
  ))
304
304
  if not options:
305
- allowed = ", ".join(f"{value:.2f}" for value in allowed_occupancies)
305
+ allowed = ", ".join(f"{value:.3f}" for value in allowed_occupancies)
306
306
  raise ValueError(
307
307
  f"no allocation reaches the target using -occ values: {allowed}"
308
308
  )
@@ -350,7 +350,7 @@ def _adjustment_options(sites, target_count, allowed_occupancies=None):
350
350
  for site, amount in zip(sites, adjustment):
351
351
  change = amount / site.multiplicity
352
352
  value = site.occupancy + change if increase else site.occupancy - change
353
- values.append(round(min(1.0, max(0.0, value)), 2))
353
+ values.append(round(min(1.0, max(0.0, value)), 3))
354
354
  if abs(sum(site.multiplicity * value
355
355
  for site, value in zip(sites, values)) - target_count) <= TOLERANCE:
356
356
  options.append(tuple(values))
@@ -428,7 +428,7 @@ def render_candidate(parsed, occupancies, target, target_counts, z, output):
428
428
  occupancy_index = site_loop.headers.index("_atom_site_occupancy")
429
429
  for site, occupancy in zip(parsed.sites, occupancies):
430
430
  tokens = list(site.row.tokens)
431
- tokens[occupancy_index] = f"{occupancy:.2f}"
431
+ tokens[occupancy_index] = f"{occupancy:.3f}"
432
432
  lines[site.row.line_index] = " " + " ".join(tokens)
433
433
 
434
434
  output = Path(output)
@@ -475,7 +475,7 @@ def process_one(source, output_root, target_formula, allowed_occupancies=None):
475
475
  for number, (occupancies, charge) in enumerate(candidates, start=1):
476
476
  output = destination / f"{Path(source).stem}-d{number}.cif"
477
477
  render_candidate(parsed, occupancies, target, target_counts, z, output)
478
- changes = [f"{site.label}={occupancy:.2f}"
478
+ changes = [f"{site.label}={occupancy:.3f}"
479
479
  for site, occupancy in zip(parsed.sites, occupancies)
480
480
  if abs(site.occupancy - occupancy) > TOLERANCE]
481
481
  print(f" {output.name}: {', '.join(changes)}; charge={charge:.8f}")
@@ -491,7 +491,7 @@ def add_arguments(parser):
491
491
  help="Target reduced formula, for example Li3YCl6.")
492
492
  parser.add_argument(
493
493
  "-occ", nargs="+", type=float,
494
- help="Allowed site occupancies, for example 0 0.25 0.5 0.75 1.",
494
+ help="Allowed site occupancies, for example 0 0.125 0.25 ... 0.875 1.",
495
495
  )
496
496
 
497
497
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pymdkit
3
- Version: 1.5.3
3
+ Version: 1.5.4
4
4
  Summary: A unified command-line toolkit for atomistic / MD structure workflows.
5
5
  Author-email: Yueda Wang <ydwang0608@ustc.edu.cn>
6
6
  License-Expression: GPL-3.0-or-later
@@ -136,7 +136,7 @@ pmk submit-vasp -subscript sub_vasp -queue slurm -max-job-num 30
136
136
  nohup pmk submit-vasp -subscript sub_vasp -queue slurm -max-job-num 30 > submit-vasp.log 2>&1 &
137
137
  pmk realloc-occ -i 66-Li4YCl6-5.cif -of chg-balance -formula Li3YCl6
138
138
  pmk realloc-occ -if cifs -of chg-balance -formula Li3YCl6
139
- pmk realloc-occ -i 66-Li4YCl6-5.cif -of chg-balance -formula Li3YCl6 -occ 0 0.25 0.5 0.75 1
139
+ pmk realloc-occ -i 66-Li4YCl6-5.cif -of chg-balance -formula Li3YCl6 -occ 0 0.125 0.25 0.375 0.5 0.625 0.75 0.875 1
140
140
  pmk substitute -i Li3YCl6.cif -se Li -sn 3 -we Na -wn 3 -on 100
141
141
  pmk substitute -i Li3YCl6.cif -se Li -sn 3 -we none -on 100
142
142
  pmk substitute -i Li96Ta6La11Cl72.cif -se Li1 Li2 -sn 20 67 -we none -on 100
@@ -214,8 +214,9 @@ the last 50% of the SDC correlation-time range, converts A^2/ps to cm^2/s by
214
214
  multiplying by `1e-4`, and reports `D_total = (D_x + D_y + D_z) / 3`.
215
215
  Each job receives `msd/group_INDEX_ELEMENT_TEMP_msd.txt`, a matching `_sdc.txt`,
216
216
  and a `_results.txt`. The root receives a compact `sigma-sdc-summary.txt` with
217
- one row per job folder. Conductivities use two decimal places; diffusion
218
- coefficients use compact scientific notation with two decimal places. If the
217
+ one fixed-width, right-aligned row per job folder. Conductivities use two
218
+ decimal places; diffusion coefficients use compact scientific notation with
219
+ two decimal places. If the
219
220
  mobile ion occupies multiple groups, conductivities are summed and diffusion
220
221
  coefficients are particle-count-weighted.
221
222
 
@@ -237,8 +238,8 @@ Wyckoff labels, and CIF layout. Every input receives `OUTPUT/INPUT_STEM/`; for
237
238
  the supplied Li4YCl6 example, the two outputs are `...-d1.cif` with `Li1=0.50`
238
239
  and `...-d2.cif` with `Li2=0.50`. Folder mode uses `-if` with the same `-of` and
239
240
  `-formula` options. Add `-occ` followed by the only permitted occupancy values;
240
- for example, `-occ 0 0.25 0.5 0.75 1` also permits the valid allocation
241
- `Li1=0.75, Li2=0.75`.
241
+ three decimal places are supported, so grids containing `0.125`, `0.375`,
242
+ `0.625`, and `0.875` are preserved exactly in generated CIF files.
242
243
 
243
244
  `gather-fs` recursively scans all job folders below the current directory. For
244
245
  VASP it follows the global `vaspout.h5 > vasprun.xml > OUTCAR` priority and
@@ -305,7 +306,7 @@ and `Cl`. Oxidation numbers remain in the separate
305
306
 
306
307
  Newly serialized floating-point values use eight digits after the decimal
307
308
  point across PMK structure, trajectory, data, report, and screen output. CIF
308
- `_atom_site_occupancy` values use two digits and
309
+ `_atom_site_occupancy` values use three digits and
309
310
  `_atom_type_oxidation_number` values use one digit. In extended XYZ, zero components
310
311
  inside the second-line `Lattice="..."` value remain `0.0`; other generated
311
312
  floating-point values use eight digits. Commands that select or concatenate
File without changes
File without changes