나는 테스트 케이스를 연구하고 있는데 각 테스트 케이스 는 ~/test
.ls -rtl
디렉터리의 수정 타임스탬프를 변경하지 않고 디렉터리에서 파일을 삭제할 수 있습니까?
답변1
파일을 삭제한 후에는 디렉터리의 타임스탬프를 재설정해야 합니다. GNU 도구를 사용한다고 가정하면 다음과 같이 작동합니다.
mtime=$(stat -c %y dir) # get the timestamp, store in $mtime
rm dir/somefile dir/someotherfile # do whatever you need
touch -d "$mtime" dir # set the timestamp back
이렇게 하면 디렉터리의 수정( ) 및 액세스( ) 타임스탬프가 mtime
원래 수정 타임스탬프로 재설정되고 변경 타임스탬프( )도 현재 시간으로 설정됩니다. 변화는 불가피하지만 신경 쓰지 않을 수도 있습니다.atime
ctime
ctime
atime
답변2
이 touch
명령은 -r
참조 파일과 동일한 타임스탬프를 가진 파일을 터치할 수 있는 옵션을 제공합니다. 그래서 당신은 이것을 할 수 있습니다 :
touch -r /dir/somefile /tmp/_thetimestamps # save the timestamps in /tmp/_thetimestamps
rm /dir/somefile # do whatever you need
touch -r /tmp/_thetimestamps /dir # set the timestamps back
-r, --reference=FILE
use this file's times instead of current time
-r Use the access and modifications times from the specified file
instead of the current time of day.
답변3
파이썬 버전입니다ikkachu의 훌륭한 답변:
https://gist.github.com/jaytaylor/ea1b6082ea5bcea7a6b65518d91238f5
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Removes a file or directory while preserving the modification time (mtime) of
the parent directory.
Pure-python implementation.
See also:
https://unix.stackexchange.com/a/565595/22709
"""
import argparse
import logging
import os
import platform
import re
import shutil
import stat
import sys
log_formatter = logging.Formatter('%(asctime)s, %(levelname)s %(message)s')
logging.basicConfig(level=logging.INFO, formatter=log_formatter)
logger = logging.getLogger(__name__)
def parse_opts(args):
parser = argparse.ArgumentParser(
description='Removes a file or directory while preserving the modification time (mtime) of the parent directory.',
argument_default=False,
)
parser.add_argument('-f', '--force', default=False, action='store_true', help='Ignore nonexistent files and arguments')
parser.add_argument('-i', '--interactive', default=False, action='store_true', help='Prompt for confirmation before taking action on a target')
parser.add_argument('--no-preserve-root', default=False, action='store_true', help="Do not treat '/' specially")
parser.add_argument('-r', '--recursive', default=False, action='store_true', help='Remove directories and their contents recursively')
parser.add_argument('-v', '--verbose', default=False, action='store_true', help='Display verbose log output')
parser.add_argument('paths', type=str, nargs='+', help='Filesystem path(s) to remove')
opts = parser.parse_args(args)
if opts.verbose:
logger.setLevel(logging.DEBUG)
return opts
# n.b. Use the appropriate input function depending on whether the runtime
# environment is Python version 2 or 3.
_input_fn = input if sys.version_info > (3, 0) else raw_input
def _prompt_for_confirmation(path, opts):
if not opts.interactive:
return True
response = _input_fn('Permanently remove "%s"? (Y/n)' % (path,))
return response in ('Y', 'y')
def require_write_permissions(path):
parent = os.path.dirname(path)
if not os.access(parent, os.W_OK):
raise Exception('Missing necessary write permission for parent directory "%s"; operation aborted' % (parent,))
def rm_preserving_parent_mtime(path, opts):
"""
Deletes the specified path, and restores the filesystem access and modified
timestamp values afterward removing path.
IMPORTANT
---------
Take note of the permission test before removing the target. These checks
verify write access to parent's parent.
Without the check, there is a risk that the file will be removed and then
setting mtime fails. When this happens, the entire purpose of this program is defeated.
"""
if not opts.no_preserve_root and (path == os.sep or (platform.system() == 'Windows' and re.match(r'^[A-Z]:%s?' % (os.sep,), path))):
raise Exception('Cowardly refusing to operate on root path')
if path in ('', '.', '..'):
raise Exception('Invalid path "%s", must have a parent directory' % (path,))
parent = os.path.dirname(path)
if path == parent:
raise Exception('Invalid path, parent directory="%s" should not equal path="%s"' % (parent, path))
st = os.stat(parent)
atime = st[stat.ST_ATIME]
mtime = st[stat.ST_MTIME]
modified = False
try:
if os.path.isfile(path):
require_write_permissions(parent)
if _prompt_for_confirmation(path, opts):
logger.debug('Removing file "%s"' % (path,))
modified = True
os.remove(path)
elif os.path.isdir(path):
if not opts.recursive:
raise Exception('Cannot remove "%s": Is a directory' % (path,))
require_write_permissions(parent)
if _prompt_for_confirmation(path, opts):
logger.debug('Removing directory "%s"' % (path,))
modified = True
shutil.rmtree(path)
else:
raise Exception('Path "%s" is not a file or directory' % (path,))
finally:
if modified:
logger.debug('Restoring access and modification timestamps for parent="%s"' % (parent,))
os.utime(parent, (atime, mtime))
def main(paths, opts):
try:
for path in paths:
rm_preserving_parent_mtime(path, opts)
return 0
except BaseException:
logger.exception('Caught exception in main')
if opts.force:
return 0
return 1
if __name__ == '__main__':
opts = parse_opts(sys.argv[1:])
sys.exit(main(opts.paths, opts))
상위 디렉터리 mtime을 유지하면서 파일을 이동하거나 삭제하는 완전한 솔루션을 보려면 다음 Python 스크립트를 참조하세요.https://gist.github.com/jaytaylor/e2e0b53baf224f4e973b252370499de7