Deleting All Files Except Ones Mentioned in Config File

Deleting all files except ones mentioned in config file

It is considered bad practice to pipe the exit of find to another command. You can use -exec, -execdir followed by the command and '{}' as a placeholder for the file, and ';' to indicate the end of your command. You can also use '+' to pipe commands together IIRC.

In your case, you want to list all the contend of a directory, and remove files one by one.

#!/usr/bin/env bash

set -o nounset
set -o errexit
shopt -s nullglob # allows glob to expand to nothing if no match
shopt -s globstar # process recursively current directory

my:rm_all() {
local ignore_file=".rmignore"
local ignore_array=()
while read -r glob; # Generate files list
do
ignore_array+=(${glob});
done < "${ignore_file}"
echo "${ignore_array[@]}"

for file in **; # iterate over all the content of the current directory
do
if [ -f "${file}" ]; # file exist and is file
then
local do_rmfile=true;
# Remove only if matches regex
for ignore in "${ignore_array[@]}"; # Iterate over files to keep
do
[[ "${file}" == "${ignore}" ]] && do_rmfile=false; #rm ${file};
done

${do_rmfile} && echo "Removing ${file}"
fi
done
}

my:rm_all;

Batch delete all files and directories except specified file and directory

@ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "keepfile=1.bat"
SET "keepdir=keep me"

FOR /d %%a IN ("%sourcedir%\*") DO IF /i NOT "%%~nxa"=="%keepdir%" RD /S /Q "%%a"
FOR %%a IN ("%sourcedir%\*") DO IF /i NOT "%%~nxa"=="%keepfile%" DEL "%%a"

GOTO :EOF

You would need to change the setting of sourcedir, keepdir and keepfile to suit your circumstances. The listing uses a setting that suits my system.

The for/d command deals with all of the directories, except that where the name+extension matches the required name, then the for repeats the action on files in the target directory, deleteing all except that which matches the required filename-to-keep.

Batch command to delete everything (sub folders and files) from a folder except one file

Here is the way I would do it:

pushd "C:\Users\data" || exit /B 1
for /D %%D in ("*") do (
rd /S /Q "%%~D"
)
for %%F in ("*") do (
if /I not "%%~nxF"=="web.config" del "%%~F"
)
popd

The basic code is taken from my answer to the question Deleting Folder Contents but not the folder but with the del command replaced by a second for loop that walks through all files and deletes only those not named web.config.

Note that this approach does not touch the original parent directory, neither does it touch the original file web.config. The great advantage of this fact is that no attributes are going to be lost (for instance, creation date and owner).

Explanation

  • change to root directory by pushd; in case of failure, skip the rest of the script;
  • iterate through all the immediate sub-folders of the root by a for /D loop and delete them recursively by rd /S with all their contents;
  • iterate through the files located in the root by a standard for loop; use the ~nx modifier of the loop variable to expand base name (n) and extension (x) of each file, compare it with the given file name (if) in a case-insensitive manner (/I) and delete the file by del only in case it does not match (not);
  • restore former working directory by popd finally;

The main problems in your code are:

  • that you compare more that the pure file name with the prefedined name, so there is not going to be found any match.
  • you needed to use case-insensitive comparison, because Windows does not care about the case of file names for searching.
  • you did not put quotation marks around the comparison expressions, so you are likely going to receive syntax error messages, depending on what special characters occur in the file names.
  • that you are using the del command only which just deletes files; to remove directories, you needed to use rd also.

How to delete all files except one from a directory using PHP?

8 years ago I wrote this quick hack that got accepted but please take on account that

  • It is platform dependent: It will work on unix-like systems only, as it depends on unix-like paths and rm and mv delete and move shell commands.
  • It requires php config to allow running system shell commands via shell_exec (Something I would not recommend unless you know what you are doing)
  • It is quite an ad-hoc answer to the proposed question, not even fancy enough to use a foreach iteration on an array of file names, which allows for a much more general solution.
  • It does not perform error capture of any kind so your script will silently continue on failure (Also capturing errors on shell_exec is not trivial since you do not get the exit code as you can do with alternatives like exec or system)

However it has the advantage of running all deletions in a single shell command and it does not require an extra exclusion lookup per processed file, which makes it run quite fast on high deletion vs. preserving ratios, if performance is what you are looking for:

    for ($i=1;$i<=2;$i++){
shell_exec ('mv /test'.$i.'/124.jpg /test'.$i.'/keep.jpg');
shell_exec ('rm /test'.$i.'/12*.jpg');
shell_exec ('mv /test'.$i.'/keep.jpg /test'.$i.'/124.jpg');
}

Anyway if you look right here a few other answers that propose an unlink based solution were added after mine, which (as discussed in the comments below) is a much better approach, to which I'd also suggest

  • Adding error handling, as unlink might fail to delete an existing file on permission issues when the file is in use or the script execution user is not allowed to modify it.

  • Always ini_get('max_execution_time'); to check your script execution timeout settings (and consider using set_time_limit to extend it for your script if necessary) before running a script processing an unknowingly long list of files.

Delete all files and folders but exclude a subfolder

Get-ChildItem -Path  'C:\temp' -Recurse -exclude somefile.txt |
Select -ExpandProperty FullName |
Where {$_ -notlike 'C:\temp\foldertokeep*'} |
sort length -Descending |
Remove-Item -force

The -recurse switch does not work properly on Remove-Item (it will try to delete folders before all the child items in the folder have been deleted). Sorting the fullnames in descending order by length insures than no folder is deleted before all the child items in the folder have been deleted.

How to exclude some directories and files from deliting in Delete Files task

After testing, pattern !(Client) works. But it also keeps the OtherJunkFolder and OtherFile in folder Client.

Pattern !(Client/ImportantFolder) does not work.

As workaround you can use a script task to delete all folders and files from the folder except those in folders Client/ImportantFolders. Please check below powershell script in a powershell task.

Get-ChildItem "$(build.artifactstagingdirectory)" | where { $_.Name -inotmatch "Client" } | Remove-Item -Recurse
Get-ChildItem "$(build.artifactstagingdirectory)/Client" | where { $_.Name -inotmatch "ImportantFolder" } | Remove-Item -Recurse

Another possible workaround is the use a copy file task to copy the folder Client/ImportantFolder to a new folder. For below example, folder Client/ImportantFolder will be copied to a new folder $(Agent.BuildDirectory)/a1 . And then point the following tasks to this new folder.

Sample Image

If your intention is to only include folder Client/ImportantFolder in your artifacts to be published in the following publish build artifacts task. The easiest way is to point Path to publish to folder Client/ImportantFolder. Then the artifacts published will only have folder Client/ImportantFolder. Check below example:

Sample Image



Related Topics



Leave a reply



Submit